gpt4 book ai didi

ios - Kingfisher 将数据缓存在 RAM 中

转载 作者:行者123 更新时间:2023-11-28 06:18:45 24 4
gpt4 key购买 nike

我喜欢新闻提要,我有以下问题,如果用户上传超过 300 条新闻,那么应用程序将已经占用超过 300 兆字节的内存。有一次在测试期间,我确实得到了 didReceiveMemoryWarning,它只帮助完全清理了 dataSource。我也用 Kingfisher缓存图像。这种情况的最佳方法是什么?缓存第一个数据,如果用户返回顶部(到最新数据),然后从缓存中加载它们,或者是否有更好的方法?谢谢。

更新:这是新闻 JSON 模型。

["peopleProperties": ["numberOfPeopleDescription": "Nobody here", "numberOfPeople": 0, "availableSeats": 0], "isPrivateStatus": false, "additionalInfo": ["note": ""], "ownerID": "", "ticketsInfo": ["tickets": []], "isTest": false, "isNewPendingRequest": false, "dateProperties": ["isEditable": true, "iso8601": "", "day": "", "endTimeStamp": 0.0, "isFlexDate": true, "isFlexTime": true, "timeStamp": 0.0], "boolProperties": ["isPartnerGeneratedCard": false, "isAutoGeneratedCard": true, "isUserCreatedCard": false, "isAdminCreatedCard": false], "location": ["formattedAddress": "692 N Robertson Blvd (at Santa Monica Blvd),West Hollywood, CA 90069,United States", "fullLocationName": "692 N Robertson Blvd", "coordinate": ["longitude": -118.38528500025966, "latitude": 34.083373986214625]], "id": "", "photoURLsProperties": ["placePhotoURLs": ["example"], "placeLogoURLs": []], "services": ["serviceURL": "", "serviceID": "41cf5080f964a520a61e1fe3", "index": 1], "version": 1, "title": "Th e Abbey Food & Bar", "ownerName": "", "phones": [:]]

更新 1. 有时会导致应用程序崩溃。我的测试 Controller

import UIKit
import SVProgressHUD
class CardTestTableViewController: UITableViewController {

// MARK: - Managers

fileprivate let firCardDatabaseManager = FIRCardDatabaseManager()
fileprivate let apiManager = ableCardsAPIManager()

// MARK: - API Manager's properties

fileprivate var firstCardsCount = 0
fileprivate var isSecondTypeRequestLaunch = false

/// Main cards array
fileprivate var cardsModels = [CardModel]()
fileprivate var firCardsModels = [CardModel]()
fileprivate var backendCardsModels = [CardModel]()

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .white
definesPresentationContext = true
requestAllData()

// table view
registerCells()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(false, animated: false)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
debugPrint("didReceiveMemoryWarning")
cardsModels.removeAll()
tableView.reloadData()
// Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if cardsModels.count > 0 {
debugPrint("cardsModels.first!.toJSON()", cardsModels.first!.toJSON(), "cardsModels.first!.toJSON()")

}
return cardsModels.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = cardTestTableViewCell(tableView, indexPath: indexPath)

let lastElement = cardsModels.count - 15
if indexPath.row == lastElement {
secondRequest(indexPath.row)
}

return cell
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 298
}


}

extension CardTestTableViewController {

fileprivate func registerCells() {
let nib = UINib(nibName: CardTestTableViewCell.defaultReuseIdentifier, bundle: Bundle.main)
tableView.register(nib, forCellReuseIdentifier: CardTestTableViewCell.defaultReuseIdentifier)
}


}

// MARK: - Cells

extension CardTestTableViewController {

fileprivate func cardTestTableViewCell(_ tableView: UITableView, indexPath: IndexPath) -> CardTestTableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CardTestTableViewCell.defaultReuseIdentifier, for: indexPath) as! CardTestTableViewCell

let card = cardsModels[indexPath.row]

cell.setupData(card)

return cell
}

}

// MARK: - Requests

extension CardTestTableViewController {

@objc fileprivate func requestAllData() {
let requestGroup = DispatchGroup()
if let topViewController = UIApplication.topViewController() {
if topViewController.isKind(of: CardViewController.self) {
SVProgressHUD.show()
}
}
firCardsModels.removeAll()
backendCardsModels.removeAll()

requestGroup.enter()
firCardDatabaseManager.getCardModelsByUserLocation(success: { [weak self] (userCardsModels) in
debugPrint("Finish +++ fir", userCardsModels.count)
self?.firCardsModels = userCardsModels
requestGroup.leave()
}) { (error) in
// TODO: - Think about it: Do not show an error, because we have cards with FourSquare
debugPrint("FIRCardDatabaseManager error", error.localizedDescription)
requestGroup.leave()
}

requestGroup.enter()
apiManager.requestCards(10, secondRequestLimit: 50, isFirstRequest: true, success: { [weak self] (cards) in
self?.backendCardsModels = cards
requestGroup.leave()
}) { (error) in
requestGroup.leave()
}

requestGroup.notify(queue: .main) { [weak self] in
guard let _self = self else { return }
_self.cardsModels.removeAll()
_self.cardsModels.append(contentsOf: _self.firCardsModels)
_self.cardsModels.append(contentsOf: _self.backendCardsModels)

self?.tableView.reloadData()
// for api manager
self?.firstCardsCount = _self.cardsModels.count

SVProgressHUD.dismiss()
}
}


fileprivate func secondRequest(_ index: Int) {
// the second request
debugPrint("swipe index", index, "firstCardsCount", firstCardsCount)

// This is for how much to the end of the deck, we ask for more cards.
let muchMoreIndex = 15
let checkNumber = firstCardsCount-1 - index - muchMoreIndex
debugPrint("checkNumber", checkNumber)

if checkNumber == 0 || checkNumber < 0 {
guard !isSecondTypeRequestLaunch else { return }
isSecondTypeRequestLaunch = true
apiManager.requestCards(0, secondRequestLimit: 50, isFirstRequest: false, success: { [weak self] (backendCards) in
DispatchQueue.main.async {
guard let _self = self else { return }
_self.cardsModels.append(contentsOf: backendCards)
_self.firstCardsCount = _self.cardsModels.count
_self.isSecondTypeRequestLaunch = false

_self.tableView.reloadData()
}

}, fail: { [weak self] (error) in
self?.isSecondTypeRequestLaunch = false
})
}
}

}

import UIKit
import Kingfisher

class CardTestTableViewCell: UITableViewCell {

@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var cardImageView: UIImageView!
@IBOutlet private weak var profileImageView: UIImageView!

override func prepareForReuse() {
cardImageView.image = nil
profileImageView.image = nil
}

func setupData(_ card: CardModel) {
downloadImages(card)
setupLabelsData(card)
}

private func downloadImages(_ card: CardModel) {
if let placeAvatarURLString = card.photoURLsProperties.placePhotoURLs.first {
if let placeAvatarURL = URL(string: placeAvatarURLString) {
cardImageView.kf.indicatorType = .activity
cardImageView.kf.setImage(with: placeAvatarURL)
} else {
cardImageView.image = UIImage(named: "CardDefaultImage")
}
} else if let eventLogoURLPath = card.photoURLsProperties.placeLogoURLs.first {
if let url = URL(string: eventLogoURLPath) {
cardImageView.kf.indicatorType = .activity
cardImageView.kf.setImage(with: url)
} else {
cardImageView.image = UIImage(named: "CardDefaultImage")
}
} else {
cardImageView.image = UIImage(named: "CardDefaultImage")
}

guard card.boolProperties.isAutoGeneratedCard != true && card.boolProperties.isAdminCreatedCard != true else {
profileImageView.image = #imageLiteral(resourceName: "ProfileDefaultIcon")
return
}

let firImageDatabaseManager = FIRImageDatabaseManager()
firImageDatabaseManager.downloadCardUserProfileImageBy(card.ownerID) { [weak self] (url, error) in
DispatchQueue.main.async {
guard error == nil else {
self?.profileImageView.image = #imageLiteral(resourceName: "ProfileDefaultIcon")
return
}
guard let _url = url else {
self?.profileImageView.image = #imageLiteral(resourceName: "ProfileDefaultIcon")
return
}
self?.profileImageView.kf.indicatorType = .activity
self?.profileImageView.kf.setImage(with: _url)
}
}
}

private func setupLabelsData(_ card: CardModel) {
titleLabel.text = card.title
}

}

更新 2。当我注释掉与 Kingfisher 框架相关的代码时,没有内存泄漏和应用程序崩溃。

最佳答案

我解决了我的问题,实际上 Kingfisher 最初将所有图像存储在 RAM 中,它具有如果应用程序收到内存警告的属性,那么它应该释放内存,但在我的情况下不是这样。所以我给 Kingfisher 设置了限制,你只能使用 1 兆字节的 RAM 内存。

我将此函数放在 AppDelegate 中并调用函数 didFinishLaunchingWithOptions

fileprivate func setupKingfisherSettings() {
ImageCache.default.maxMemoryCost = 1
}

关于ios - Kingfisher 将数据缓存在 RAM 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44325074/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com