您的位置:首页 > 移动开发 > Swift

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

2015-01-02 13:05 986 查看
对fetch结果进行排序:

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

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

转载请注明出处:/article/9358012.html

源代码地址: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中使用起来十分简便。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: