2015-01-19 6 views
0

Как человек, который является совершенно новым для Swift и CoreData, я уверен, что я собираюсь сделать это неправильно и надеюсь, что кто-то сможет помочь.iOS Swift CoreData Асинхронная загрузка данных изображения

Справочная информация: Я загружаю JSON по API и кеширую содержимое локально на iPad в CoreData. Как часть процесса, мне нужно загрузить маленькую миниатюру изображения, которую я также храню в CoreData (как Transformable).

я делал: Моей первой реализацию загруженных изображений и сохранила их в CoreData, но несмотря на то, что в настоящее время запускается из фонового потока (обратного вызова после вызова API), фактическая загрузка изображений, кажется, вызывает приложение, чтобы повесить:

let data = NSData(contentsOfURL: imgURL) 
if let imageData = data { 
    coreDataEntity.thumbnail = imageData 
} 

То, что я сейчас делаю: Я с тех пор обновил свой код к следующему:

func downloadImage(url: NSURL, cdEntity: CoreDataEntity, moc: NSManagedObjectContext, handler: ((image: UIImage?, cdEntity: CoreDataEntity, moc: NSManagedObjectContext, NSError!) -> Void)) 
{ 
    var imageRequest: NSURLRequest = NSURLRequest(URL: url) 
    NSURLConnection.sendAsynchronousRequest(imageRequest, 
     queue: NSOperationQueue.mainQueue(), 
     completionHandler: {response, data, error in 
      handler(image: UIImage(data: data), cdEntity: cdEntity, moc: moc, error) 
    }) 
} 

func setImage(image: UIImage?, cdEntity: CoreDataEntity, moc: NSManagedObjectContext, error: NSError?) { 
    cdEntity.thumbnail = image 
    save(moc) 
} 

I-й ан называют код таким образом:

downloadImage(imgURL, coreDataEntity, moc, { (image, cdEntity, moc, error) -> Void in 
    setImage(image, cdEntity, moc, error) 
}) 

Делая это, я не получаю никаких блоков в основном потоке, что я замечаю. Проверяя файл sqlite с устройства, похоже, что данные устанавливаются правильно, но изображения не отображаются в пользовательском интерфейсе.

Является ли мой метод совершенно неправильным? Если нет, как я могу сообщить пользовательскому интерфейсу, что базовая модель данных была обновлена ​​таким образом, чтобы вызвать обновление? Какую функцию можно вызвать для обновления определенной строки/ячейки таблицы/uicollectionview?

+0

"и кэширование контента локально на iPad в CoreData". Errr ... почему? Система загрузки URL-адресов уже обрабатывает кеширование. Если вы хотите, чтобы кэшированные данные сохранялись на диске, все, что вам нужно сделать, это включить его. См. Документацию для «NSURLCache». – quellish

+0

Я рад исследовать альтернативные варианты кеширования, но URL-адрес, указывающий на изображение (хранящийся на S3), скорее всего, изменится по мере создания новых токенов, предоставляющих доступ к нему. Мое предположение заключалось в том, что это приведет к аннулированию NSURLCache. – djbp

ответ

1
  1. Ваши обратные вызовы NSURLConnection происходят в главной очереди. Это одна из причин, по которой ваше приложение блокируется.

  2. Контекст управляемого объекта, по крайней мере, в коде, который вы опубликовали, не соответствует правилам параллелизма основных данных. У вас есть выбор между ограничением потоков (к сожалению, устаревшим по умолчанию) и удержанием очереди.

С ограничением потока вы можете использовать контекст управляемого объекта из потока, где он был создан. Если вы создали контекст управляемого объекта в основном потоке (или очереди), вы можете использовать его только там, поэтому любая операция Core Data, которую вы выполняете в этом контексте, блокирует основной поток и, в свою очередь, пользовательский интерфейс.

Использование ограничения очереди (почти) любая операция в контексте управляемого объекта должна пройти либо методы performBlock:, либо performBlockAndWait:. Блокированный блок выполняется в последовательной очереди контекста. Это намного меньше, чем неудача склонного удержание нити и была рекомендована практикой параллельности так прошивки 5.

Если нет, то как я могу сообщить, что пользовательский интерфейс модель данных ядер были обновлена ​​таким образом, что будет вызвать обновление? Какую функцию можно вызвать для обновления определенной строки/ячейки таблицы/uicollectionview?

Обычно это делается с использованием NSFetchedResultsController, который отслеживает контекст управляемого объекта для изменений, относящихся к его запросу на выборку.Когда начальная выборка заполняет контроллер, он будет прослушивать изменения контекста, которые влияют на объекты, указанные в запросе выборки. Когда происходят соответствующие изменения, контроллер сообщает об этом делегату через обратные вызовы.

Смежные вопросы