Ошибка и медленная прокрутка при загрузке изображений TableView из CoreData
Проблема: процесс загрузки изображений в табличное представление с использованием их путей, которые хранятся в базе данных Core Data, работает нормально, но пользовательский опыт не идет хорошо. Свиток медленный и глючный.
Примечания импортеров:
- Для моей локальной базы данных я использую Core Data
- Я не сохраняю само изображение в Базовых данных, только их путь (имя изображения)
- Что касается табличного представления DataSource, я использую массив типа Person, который содержит идентификатор и имя Img (строки Table View равны array.Count). -Это URL, из которого я получаю мой Json (Проверьте это) - Json Link
- Все объекты внутри БД базовых данных
- Насколько я знаю, я сделал все обновления пользовательского интерфейса в главном журнале
- После каждой проверки я перезагружаю таблицу.
Это шаги, которые выполняются в правильной последовательности:
Получить данные с помощью NSURLSession - DataTask. После этого он выполняет "синтаксический анализ" и проверяет, существует ли каждый объект (в цикле for) в БД базовых данных, а затем добавляет его переменные в массив источника данных Table View и перезагружает данные.
1)
let request = NSMutableURLRequest(URL: dataSourceURL!)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
println("error=\(error)")
return
}
if data != nil {
let datasourceDictionary = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as NSDictionary
var DataArray = datasourceDictionary["descisions"] as NSArray
//Convert it to useable array
for var i = 0 ; i < DataArray.count ; i++ {
let ID_s = DataArray[i]["ID"]! as Int
//For each Object from the Json array i'm check if he is exisitng in the local DB
var ConvertetdID = Int32(ID_s)
let object : Lockdown? = self.CheckIfObjectExistInDBbyID(ConvertetdID)
//CheckIfExists - if it does , it return an object with the correct values
if object != nil {
//exists - load file from Core Data
let imgname = object!.imgPath
let photoRecord = PhotoRecord(name:"\(ConvertetdID)", url:imgname)
self.photos.append(photoRecord)
//TableView object array (photos)
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
//After each check reload the tableView
}
}
}
}
task.resume()
Метод, который проверяет, существует ли он в основной базе данных или нет (метод получает идентификатор и возвращает объект, если существует, и ноль, если нет:
func CheckIfObjectExistInDBbyID(id : Int32) -> Lockdown? {
let appDelegate =
UIApplication.sharedApplication().delegate as AppDelegate
let managedContext = appDelegate.managedObjectContext!
var request : NSFetchRequest = NSFetchRequest(entityName: "Lockdown")
request.predicate = NSPredicate(format: "id = %d", id)
var error : NSError?
request.fetchLimit = 1
var count : Int = managedContext.countForFetchRequest(request,error: &error)
if count == 0 {
// println("Error : \(error?.localizedDescription)")
println("Object \(id) Dosent exist in CoreData")
return nil
}
println("Object \(id) exist in CoreData")
let result = managedContext.executeFetchRequest(request, error: &error) as NSArray!
let lockdown = result.objectAtIndex(0) as Lockdown
println(lockdown.id)
return lockdown
}
Метод cellForRowAtIndexPath
let cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier", forIndexPath: indexPath) as UITableViewCelllet photoDetails = photos[indexPath.row]
cell.textLabel.text = photoDetails.name as String
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
var myPathList : NSArray = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true)
var myPath = myPathList[0] as String
myPath = myPath.stringByAppendingPathComponent("\(photoDetails.name).png")
var image : UIImage = UIImage(contentsOfFile: myPath)!
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = image
}
}
return cell
Любые предложения, что является причиной проблемы?
1 ответ
Вы не должны всегда загружать образ с диска, это медленно. Вместо этого сначала загрузите образ с диска, а затем сохраните его в кеше (в памяти). Проверьте, кэшировано ли изображение, прежде чем загружать его с диска.
Вам нужно очистить кеш, если он становится слишком большим или вы получаете предупреждение о памяти.
Расширенные версии могут предварительно кэшировать некоторые изображения для ячеек, которые находятся чуть ниже текущей позиции прокрутки.
Вы можете использовать библиотеку для этого, возможно, SDWebImage с URL-адресами файлов (я этого не пробовал).
Ошибка состоит в том, что ваш асинхронный блок не проверяет, что ячейка не была повторно использована до загрузки изображения. Если это так, то в повторно используемой ячейке появится неправильное изображение (пока оно не будет заменено другим изображением). Чтобы исправить, захватить indexPath
в блоке и получить клетку для этого indexPath
как только изображение загружено - если табличное представление возвращается nil
тогда ячейка больше не видна, и вам не нужно ничего делать, кроме как кэшировать изображение для будущего использования.