iOS Swift教程 Core Data (五)NSFetchedResultsController 上

本文介绍如何使用NSFetchedResultsController简化UITableView与CoreData的结合,包括FetchRequest创建、数据排序、分区展示及缓存机制。

在前四节的实例中,我们都使用了table view作为core data的数据显示容器,这是因为core data能够很好的和table view进行配合。创建fetch request,获取一组managed object,将结果作为table view的数据源。UITableView和Core Data是通过NSFetchedResultsController联系在一起的。正确的使用NSFetchedResultsController将使得只用写少量的代码就让table使用core data做数据源。在这一节中,我们将会学习如何使用这个类以及什么时候应该使用它。

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

源代码地址:https://github.com/dnawym/StudySwift/tree/master/CoreData/WorldCup

World Cup app:

这一节的示例程序是一个用于显示世界杯积分榜的应用程序。这个程序会将参加世界杯的所有队伍现在主页上。点击任意国家的cell将增加这个国家的获胜次数。拥有最高获胜次数的过奖将赢得世界杯。这个计分规则十分简单,但是足够演示如何使用NSFetchedResultsController了。


这个程序由一个有20个cell的table view构成,每个cell代表一个国家,蓝色处为国旗位置。

从Fetch Request开始:

修改ViewController.swift,引入CoreData并添加成员变量

import CoreData
    var fetchedResultsController: NSFetchedResultsController!
在viewDidLoad中添加以下代码:
    override func viewDidLoad() {
        super.viewDidLoad()

        //  创建fetch request
        let fetchRequest = NSFetchRequest(entityName: "Team")
        
        // 创建Controller,提供执行上下文-managedObjectContext
        fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: nil, cacheName: nil)
        
        // 执行fetch request
        var error: NSError? = nil
        if (!fetchedResultsController.performFetch(&error)) {
            println("Error: \(error?.localizedDescription)")
        }
    }
performFetch的返回值是一个Bool变量,true代表成功,false代表失败。而执行的结果存放在controller的fetchedObjects属性中,通过objectAtIndexPath方法,可以访问到fetch的结果。
添加以下代码:

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
      
        return fetchedResultsController.sections!.count
    }
  
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let sectionInfo = fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
        
        return sectionInfo.numberOfObjects
    }
 由于NSFetchedResultsController不能只使用简单的fetch request,需要为其提供SortDescriptor,否则,程序会crush,添加以下代码到初始化fetch request位置:

        let sortDescriptor = NSSortDescriptor(key: "teamName", ascending: true)
        fetchRequest.sortDescriptors = [sortDescriptor]
程序执行效果如下:

通过点击cell修改数据:

由于Core Data将整数存储为NSNumber,这里需要unwarp wins在修改它,再转换为NSNumber

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
        
        let team = fetchedResultsController.objectAtIndexPath(indexPath) as Team
        
        let wins = team.wins.integerValue
        team.wins = NSNumber(integer: wins + 1)
        coreDataStack.saveContext()
        
        tableView.reloadData()
    }
 程序执行结果如下:


分区:

世界杯有六个区,我们也按这六个区对国家进行section划分

修改viewDidLoad,增加sectionNameKeyPath

        fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: "<span style="color:#ff0000;">qualifyingZone</span>", cacheName: nil)
显示section名

    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let sectionInfo = fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
        return sectionInfo.name
    }
修改sort descriptor,让结果首先按zone排序,相同的zone按输赢多少排序,胜场相同按字母序排序。

        let zoneSort =
        NSSortDescriptor(key: "qualifyingZone", ascending: true)
        let scoreSort =
        NSSortDescriptor(key: "wins", ascending: false)
        let nameSort =
        NSSortDescriptor(key: "teamName", ascending: true)
        fetchRequest.sortDescriptors = [zoneSort, scoreSort, nameSort]
这里需要将qualifyingZone作为第一个key,因为我们想使用section作为分隔。

Cache数据:

对数据进行遍历和排序需要花费大量的时间,尤其是在数据量很大的时候,此时,我们可以使用NSFetchResultsController的缓存机制来解决这个问题

        fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: "qualifyingZone", cacheName: "<span style="color:#ff0000;">worldCup</span>")






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值