UITableView 和 NSFetchedResultsController 的内存泄漏
Posted
技术标签:
【中文标题】UITableView 和 NSFetchedResultsController 的内存泄漏【英文标题】:Memory leak with UITableView and NSFetchedResultsController 【发布时间】:2015-04-11 20:27:38 【问题描述】:我有一个 UITableView,其内容由获取 CoreData 的 NSFetchedResultsController 管理。我有两种类型的表格视图单元格,一种带有图像,一种没有图像。图像由 UIDocument 处理,并保存在 iCloud 通用文档容器中,并由客户端名称引用。
当屏幕上有许多用户生成的图像时,单元格会被生成和重用,我的程序的内存使用率越来越高。大约 110 mb,我收到内存不足警告。
我怀疑我的 tableView 单元格中的 prepareForReuse() 方法没有正常工作。
这是我的 UITableViewCell 现在的样子:
class ClientTableViewCell: UITableViewCell
@IBOutlet weak var clientName: UILabel!
@IBOutlet weak var clientModifiedDate: UILabel!
@IBOutlet weak var profileImage: UIImageView!
let dateFormatter = NSDateFormatter()
var document: MyDocument?
var documentURL: NSURL?
var ubiquityURL: NSURL?
var metaDataQuery: NSMetadataQuery?
var myClient : Client?
didSet
updateClientInfo()
override func prepareForReuse()
super.prepareForReuse()
clientName.text = nil
clientModifiedDate.text = nil
if let mc = myClient
if mc.imageurl != ""
if let p = profileImage
p.image = nil
else
NSLog("nil document")
else
NSLog("nil client")
func updateClientInfo()
if myClient != nil
clientName.text = myClient!.name
dateFormatter.dateStyle = .ShortStyle
let dispDate = dateFormatter.stringFromDate(NSDate(timeIntervalSinceReferenceDate: myClient!.dateModified))
clientModifiedDate.text = dispDate
if let imageName = myClient?.imageurl
if myClient?.imageurl != ""
var myClientName : String!
myClientName = myClient!.name
metaDataQuery = NSMetadataQuery()
metaDataQuery?.predicate = NSPredicate(format: "%K like '\(myClientName).png'", NSMetadataItemFSNameKey)
metaDataQuery?.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "metadataQueryDidFinishGathering:",
name: NSMetadataQueryDidFinishGatheringNotification,
object: metaDataQuery!)
metaDataQuery!.startQuery()
func metadataQueryDidFinishGathering(notification: NSNotification) -> Void
let query: NSMetadataQuery = notification.object as! NSMetadataQuery
query.disableUpdates()
NSNotificationCenter.defaultCenter().removeObserver(self, name: NSMetadataQueryDidFinishGatheringNotification, object: query)
query.stopQuery()
let results = query.results
if query.resultCount == 1
let resultURL = results[0].valueForAttribute(NSMetadataItemURLKey) as! NSURL
document = MyDocument(fileURL: resultURL)
document?.openWithCompletionHandler((success: Bool) -> Void in
if success
if let pi = self.profileImage
pi.image = self.document?.image
else
println("iCloud file open failed")
)
else
NSLog("Could not find profile image, creating blank document")
如果您不熟悉 iCloud 和 UIDocument,您可能想知道我为什么要查询元数据来获取这些图像/文档。如果您知道在无处不在的容器中获取这些图像/文档的可靠方法,我会全力以赴。它会在表格视图单元格滚动期间导致此弹出效果。
这是我填充单元格的函数:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
//set the client
let client = clients.fetchedObjects![indexPath.row] as! Client
//set the correct identifier
if let imageurl = client.imageurl as String?
if imageurl == ""
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifierNoImage, forIndexPath: indexPath) as? ClientTableViewCell
cell!.myClient = client
return cell!
else
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? ClientTableViewCell
cell!.myClient = client
return cell!
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifierNoImage, forIndexPath: indexPath) as? ClientTableViewCell
cell!.myClient = client
return cell!
我原本打算使用属性 imageurl 来存储客户端配置文件图像的名称和 url,但由于无处不在的容器 url 对于每个设备都是唯一的,所以我现在只使用它来检测是否存在带有此的图像客户与否。
我已经有这个问题好几个星期了,似乎无法确定。任何指导将不胜感激!
工作台:Xcode 6.3 和 Swift 1.2。
【问题讨论】:
我遇到了完全相同的问题,仪器在 uitableview 单元格上显示泄漏,我使用的唯一额外的东西是领域,并且在我的代码上我已经验证没有任何保留周期。 :( 【参考方案1】:解决了我自己的内存泄漏问题!在此答案的帮助下:[UIDocument never calling dealloc
我正在查询 UIDocuments 并且从未关闭它们。这就是为什么 ARC 没有清理我未使用的 UIDocuments。上面的链接有 Object C 版本,但是对于使用 Swift 的人,在使用它们后尝试这些行来关闭您的文档:
document?.updateChangeCount(UIDocumentChangeKind.Done)
document?.closeWithCompletionHandler(nil)
哇!很高兴这场混乱结束了。希望这对某人有帮助!
【讨论】:
以上是关于UITableView 和 NSFetchedResultsController 的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章
使用 xmpp 获取 XMPPGroupCoreDataStorageObject,但 NSManagingContextDidSaveChangesNotification 似乎不起作用
UITableView backgroundColor 和 UITableView.appearance
UIView 与 UITableview 和 UIImageview,使用 reloadData 访问 UITableview