NSFetchedResultsController导致延迟segue

时间:2015-07-05 11:58:16

标签: ios core-data delay nsfetchedresultscontroller uistoryboardsegue

我正在构建一个类似于iphone上的Apples Photos应用程序的应用程序。使用Master-Detail界面,用户选择一个专辑并被带到显示一堆照片的UICollectionViewController。对于主视图控制器和详细视图控制器,我使用NSFetchedResultsControllers从数据库访问对象。现在不幸的是,当选择一个专辑时会出现非常明显的延迟,这是由NSFetchedResultsController提取项目的细节引起的。

由于苹果照片应用程序会立即响应,并且在点击后准备好所有照片,我想知道他们是如何做到的。

这是最好的做法吗?

代码示例

//DetailViewController.swift

// lazy frc
var fetchedResultsController: NSFetchedResultsController {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }

    let fetchRequest = NSFetchRequest()
    // Edit the entity name as appropriate.
    let entity = NSEntityDescription.entityForName("Photo", inManagedObjectContext: self.context)
    fetchRequest.entity = entity

    // Set the batch size to a suitable number.
    fetchRequest.fetchBatchSize = 20

    // Edit the sort key as appropriate.
    let sortDescriptor = NSSortDescriptor(key: "photoID", ascending: false)
    let sortDescriptors = [sortDescriptor]

    fetchRequest.sortDescriptors = [sortDescriptor]

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.context, sectionNameKeyPath: nil, cacheName: "ernesto")
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

    var error: NSError? = nil
    if !_fetchedResultsController!.performFetch(&error) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        //println("Unresolved error \(error), \(error.userInfo)")
        abort()
    }

    return _fetchedResultsController!
}
var _fetchedResultsController: NSFetchedResultsController? = nil


// MARK: - UICollectionViewDataSource
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! PhotoCell
    let item = self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject
    cell.backgroundColor = UIColor.yellowColor()
    //the following line is commented out intentionally to make sure the delay is not caused by setting the image
    //cell.imageView.image = UIImage(data: item.valueForKey("image") as! NSData)
    return cell
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    let sectionInfo = self.fetchedResultsController.sections![section] as! NSFetchedResultsSectionInfo
    return sectionInfo.numberOfObjects
}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

1 个答案:

答案 0 :(得分:1)

问题是您使用CoreData存储图片而苹果没有。虽然文件大小没有限制,但是您的库可以使用它的总大小,获取文件所需的时间比在文件结构中打开文件夹要长。当您向应用添加图片时,这会变得更糟,因为查询将返回越来越多的数据。这是除了每个添加的照片都会增长的应用大小的补充。您应该将pics存储在文件系统(以及CoreData中的路径)或库本身中,而不是CoreData。

如果您使用核心数据路由,您可以使用多种技术来加速从分批查询到查询计数以构建集合视图以及仅显示当前正在显示的单元格中的图像。

另一种方法是将每张照片以全分辨率存储两次,将一张照片以更小的尺寸存储。较小的一个是用户显示集合视图,集合和细节之间的动画,在最初的几微秒内,在全分辨率图片到达之前,照片将显示在详细视图中。