对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中使用起来十分简便。