У меня есть UITableView с его содержимым, которым управляет NSFetchedResultsController, получающая CoreData. У меня есть два типа ячеек таблицы, один с изображением и один без изображения. Изображения обрабатываются UIDocument и хранятся в контейнере вездесущих документов iCloud и ссылаются на имя клиента.Утечка памяти с помощью UITableView и NSFetchedResultsController
Поскольку ячейки генерируются и используются повторно, когда на экране появляется много изображений, созданных пользователем, использование памяти моей программы увеличивается и увеличивается. Около 110 мб, я получаю предупреждение о низкой памяти.
Я подозреваю, что мой метод prepareForReuse() в моей таблице tableView не выполняет свою работу правильно.
Вот что выглядит мой 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.