iOS Swift教程 Core Data (四)Fetch进阶 下

对fetch结果进行排序:

NSFetchRequest的一个强大特性是可以对搜索的结果进行排序,我们只需要传递NSSortDescriptor给它即可。这些排序实现在SQLite中而非在内存中,因此是非常高效的。

添加3个用于排序的lazy变量,其中第一个变量传入了一个selector,当我们对字符串进行排序时,苹果推荐使用localizedStandardCompare,这样才能保证程序在不同语言环境下,排序的结果都是正确的。

转载请注明出处:http://blog.csdn.net/yamingwu/article/details/42340709

源代码地址:https://github.com/dnawym/StudySwift/tree/master/CoreData/Bubble%20Tea%20Finder

    lazy var nameSortDescriptor: NSSortDescriptor = {
        var sd = NSSortDescriptor(key: "name", ascending: true, selector: "localizedStandardCompare:")
        return sd
    }()
    
    lazy var distanceSortDescriptor: NSSortDescriptor = {
        var sd = NSSortDescriptor(key: "location.distance", ascending: true)
        return sd
    }()
    
    lazy var priceSortDescriptor: NSSortDescriptor = {
        var sd = NSSortDescriptor(key: "priceInfo.priceCategory", ascending: true)
        return sd
    }()
和之前类似,在didSelectRowAtIndexPath的switch case中添加以下分支:

        case nameAZSortCell:
            selectedSortDescriptor = nameSortDescriptor
        case nameZASortCell:
            selectedSortDescriptor = nameSortDescriptor.reversedSortDescriptor as? NSSortDescriptor
        case distanceSortCell:
            selectedSortDescriptor = distanceSortDescriptor
        case priceSortCell:
            selectedSortDescriptor = priceSortDescriptor
执行程序,选择按名字倒序结果如下:




异步fetch:

到现在为止,我们已经学习了很多关于NSFetchRequest的知识,但是这些方法都会阻塞主线程指导fetch的结果被返回。这样会给用户带来不好的体验。

接下来,我们看看,如何实现异步fetch。

定义异步请求:

var asyncFetchRequest: NSAsynchronousFetchRequest!
修改viewDidLoad:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        //fetchRequest = coreDataStack.model.fetchRequestTemplateForName("FetchRequest")
        
        // 可以将asyncFetchRequest看做是普通fetchRequest的一个warpper
        fetchRequest = NSFetchRequest(entityName: "Venue")
        
        // 异步请求由两部分组成:普通的request和completion handler
        // 返回结果在finalResult中
        asyncFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest, completionBlock: {
            [unowned self] (result: NSAsynchronousFetchResult!) -> Void in
            self.venues = result.finalResult as [Venue]
            self.tableView.reloadData()
        })
        
        // 执行异步请求调用executeRequest而不是executeFetchRequest
        var error: NSError?
        let results = coreDataStack.context.executeRequest(asyncFetchRequest, error: &error)
        
        // executeRequest会立即返回,这里我们在异步请求的completion handler中处理返回结果并更新table view
        if let persistentStoreResults = results {
            // return immediately, cancel here if you want
        } else {
            println("Could not fetch \(error), \(error!.userInfo)")
        }
        
        fetchAndReload()
    }
类似于其它异步请求,可以使用cancel()函数取消这个请求。
修改CoreDataStack.swift

    // 异步fetch不支持默认的concurrencyType,这里修改为.MainQueueConcurrencyType
    context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
修改ViewController.swift,因为采用异步实现,venues数组在fetch操作完成前是nil,所以需要给venues数组赋空

var venues: [Venue]! = []
至此,就完成了异步fetch,我们没有修改过滤和排序的fetch方法,它们仍然使用的是普通的NSFetchRequest来更新table view。
批量更新:
只更新少量数据,使用之前讲到的方法是可以的,但是如果你要一次更新上百条数据,上述方法需要大量的时间和内存,因为每更新一个属性,就需要把所有的对象都读入内存。iOS 8苹果引入了批量更新操作来更新Core Data对象而不需要将任何东西fetch到内存中,这就大大的减少了程序执行时间和内存的消耗。下面我们会标记所有商家为“favorite”

这个方式绕过了NSManagedObjectContext而直接操作persistent store。

在ViewController的viewDidLoad的super.viewDidLoad后添加如下代码:

        let batchUpdate = NSBatchUpdateRequest(entityName: "Venue")
        batchUpdate.propertiesToUpdate = ["favorite" : NSNumber(bool: true)]
        batchUpdate.affectedStores = coreDataStack.psc.persistentStores
        batchUpdate.resultType = .UpdatedObjectsCountResultType
        
        var batchError: NSError?
        let batchResult = coreDataStack.context.executeRequest(batchUpdate, error: &batchError) as NSBatchUpdateResult?
        
        if let result = batchResult {
            println("Recored updated \(result.result)")
        } else {
            println("Could not update \(batchError), \(batchError!.userInfo)")
        }
编译运行,console会输出

批量更新类似还可以用在聊天和邮件程序的“标记所有消息为已读”功能上。只是需要注意的是,由于没有使用NSManagedObjectContext,批量更新没法使用任何validation功能,我们需要保证在使用这个方式更新Core Data前,对数据进行validate。


至此,我们就完成了第四个实例,这一节我们学会了如何使用predicate和sort descriptor来控制fetch的结果,此外还学会了iOS 8对Core Data增强的新功能-异步fetch和批量fetch。下一节,我们将继续学习fetch-NSFetchResultsController,这个辅助类使得Core Data在Table View中使用起来十分简便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值