Chapter 17 Core Data iOS 8 -Swift Programming cookBook 读书笔记

概述

以下是需要明白的概念:

  1. Persistent store: 固态存储,表示存储在Nand flash的真实数据库,我们不会之间用这个对象
  2. Persistent store coordinator: 固态存储协调者,负责协调从固态存储里面读写数据,是managed object context和固态存储的桥梁
  3. Managed object model (MOM):一个简单的存在磁盘上的文件,代表我们的数据模型
  4. Managed object: 代表了我们希望存在Core Data里面的entity,对应于一般的数据库而言,entity就是table的概念,类型是NSManagedObject,由Managed object context (MOC)存储,构成Managed object model (MOM),通过Persistent store coordinator存储在Persistent store里面
  5. Managed object context (MOC): 当你建立了一个Core data对象,设置属性,对他进行操作。所有的这些都有MOC完成。

17.1 批量更新数据库

用NSBatchUpdateRequest,步骤:
1. 声明一个NSBatchUpdateRequest
2. 然后要写断言,predicate
3. 执行,用managedObjectContext的executeRequest:error:

let batch = NSBatchUpdateRequest(entityName: entityName)
        batch.propertiesToUpdate = ["age" : 18]
        batch.predicate = NSPredicate(format: "age < %@", 18 as NSNumber)
        batch.resultType = .UpdatedObjectsCountResultType

        var batchError: NSError?
        let result = managedObjectContext!.executeRequest(batch, error: &batchError)
        if result != nil {
            if let theResult = result as? NSBatchUpdateResult {
                if let numberOfAffectedPersons = theResult.result as? Int {
                    println("result is \(numberOfAffectedPersons)")
                }
            }
        } else {
            if let error = batchError {
                println("Could not perform batch request. Error = \(error)")
            }
        }

17.2 写到Core Data

用NSEntityDescription的insertNewObjectForEntityForName:inManagedObjectContext:, 先要分配一个entity的对象,然后对对象进行修改,然后在存进去,逻辑有些奇怪。其实是在没有save之前,都没有对磁盘里面的数据库进行操作,是对缓存里的进行操作。任何对数据库有修改的操作,都需要save操作。

let entityName = NSStringFromClass(Person.classForCoder())

    func populateDatabase() {

        for counter in 0..<1000 {
            let person = NSEntityDescription.insertNewObjectForEntityForName(entityName, inManagedObjectContext: managedObjectContext!) as! Person
            person.firstName = "First name \(counter)"
            person.lastName = "Last name \(counter)"
            person.age = NSNumber(unsignedInt: arc4random_uniform(120))
        }

        var savingError: NSError?
        if managedObjectContext!.save(&savingError) {
            println("save to database")
        } else {
            if let error = savingError {
                println("Failed to save to database Error = \(error)")
            }
        }
    }

17.3 从Core Data读数据

用NSFetchRequest,先新建一个fetchRequest,然后再执行fetch操作。

let fetchRequest = NSFetchRequest(entityName: entityName)
        fetchRequest.predicate = NSPredicate(format: "age > %@", 18 as NSNumber)
        var requestError: NSError?
        let persons = managedObjectContext!.executeFetchRequest(fetchRequest, error: &requestError) as! [Person!]
        if persons.count > 0 {
            var count = 1
            for person in persons {
                println("Person \(count) first name = \(person.firstName)")
                println("Person \(count) last name = \(person.lastName)")
                println("Person \(count) age = \(person.age)")
                count++
            }
        } else {
        println("Could not find any Person")
        }

17.4 删除数据

用NSManagedObjectContext的deleteObject, 然后再save,这个逻辑也满怪的。理由同17.2

if persons.count > 0 {
            let lastPerson = persons.last
            managedObjectContext!.deleteObject(lastPerson!)
            var savingError:NSError?
            if managedObjectContext!.save(&savingError) {
            println("deleted")
        } else {
            if let error = savingError {
            println("fail to delete last person. Error = \(error)")
            }
          }
        }

17.5 排序

创建NSSortDescriptor,然后执行fetch操作

let fetchRequest = NSFetchRequest(entityName: "Person")
        let ageSort = NSSortDescriptor(key: "age", ascending: true)
        let firstNameSort = NSSortDescriptor(key: "firstName", ascending: true)
        fetchRequest.sortDescriptors = [ageSort,firstNameSort]

        var requestError:NSError?
        let persons = managedObjectContext!.executeFetchRequest(fetchRequest, error: &requestError) as! [Person!]
        for person in persons {
            println("First name = \(person.firstName)")
            println("Second name = \(person.lastName)")
            println("Age = \(person.age)")
        }

17.6 在TableView里面显示Core data数据

用NSFetchedResultsController, 其实就是取代17.5讲的fetch,用NSFetchedResultsController来执行fetch操作,从而由iOS来解决一次取多少,如何重复取的问题。下面是他的一些重要的概念:

  • sections:属性,类型是NSArray,通过key path(sectionNameKeyPath)来归类数据;
  • objectAtIndexPath: 实例方法,返回一个managed object,也就是一个attitude对象
  • fetchRequest: 属性,NSFetchRequest对象

把fetch的操作交给NSFetchedResultsController去做,其他的部分是和前面的一样的

let fetchRequest = NSFetchRequest(entityName: "Person")
        let ageSort = NSSortDescriptor(key: "age", ascending: true)
        let firstNameSort = NSSortDescriptor(key: "firstName", ascending: true)
        fetchRequest.sortDescriptors = [ageSort,firstNameSort]

        frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
        frc.delegate = self
        var fetchingError: NSError?
        if frc.performFetch(&fetchingError) {
            println("SuccessFully fetched")
        } else {
            println("Failed to fetch")
        }

以下是NSFetchedResultsControllerDelegate的一些重要的delegate,用于通知fetch request执行的过程点:

  • controllerWillChangeContent:当managedObjectContext将要改变的时候,常常是在另外一个类里面被改变,需要准备重新刷新table view,用tableview的beginUpdates方法
  • controllerDidChangeContent: 当managedObjectContext已经被刷新了,需要在这个方法里面调用tableview的endUpdates,通知table view结束刷新。
  • controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: 当某一个特定的操作发生的时候,比如如果删除一个对象,forChangeType会包含NSFetchedResultsChangeDelete,如果插入了一个对象,会包含NSFetchedResultsChangeInsert,如果有对象被更新,也会调用这个函数

17.7 Core Data 的关系

Coredata的relationship可以是一对一,一对多,多对多
Coredata里面的一对一关系比较特殊,A和B,一对一,A可以知道B,但是B不知道A
t.b.d

17.8 后台取数据

注意managed object并不是线程安全的,不要在不同的线程之间使用,例如:你如果在后台取了managed object,那么不能在主线程直接使用这些managed object,而应该在主线程用objectWithID来取。objectWithID接受NSManagedObjectID的对象,所以在你的后台线程中,其实只需要取得ID,然后把ID给主线程。

步骤:

  1. 用NSManagedObjectContext的初始化函数创建一个background context,使用NSPrivateQueueConcurrencyType参数,会返回一个由自己私有dispatch队列的context。
  2. 设置persistentStoreCoordinator
  3. performBlock ,取得id
  4. 跳回主线程,取得managed object
let backgroundContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
        backgroundContext.persistentStoreCoordinator = persistentStoreCoordinator

        backgroundContext.performBlock { [weak self]() -> Void in
            let fetchRequest = NSFetchRequest(entityName: self!.entityName)
            fetchRequest.fetchBatchSize = 20
            fetchRequest.predicate = NSPredicate(format: "age > %@", 18 as NSNumber)
            fetchRequest.resultType = .ManagedObjectIDResultType
            var requestError: NSError?
            let personIds = backgroundContext.executeFetchRequest(fetchRequest, error: &requestError) as! [NSManagedObjectID]
            if requestError == nil {
                dispatch_async(dispatch_get_main_queue(), {[weak self] () -> Void in
                for personId in personIds {
                    let person = self!.managedObjectContext!.objectWithID(personId) as! Person
                    self!.mutablePersons.append(person)
                }
                println("get persons")
                })
            }else {
                println("Fail to execute the fetch request")
            }

17.9 自定义数据类型

如果你认为Core data提供的数据类型不能满足你的需要,比如,你想要UIColor。那么你可以自定义类型,用transformable属性。
t.b.d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值