原文地址:What's New in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0

翻译者:肖品,原创文章转载请著名出处。

Core Data在 macOS 10.12 , iOS 10.0, tvOS 10.0和watchOS 3.0中的新特性

This document describes the new areas of functionality in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0. Please note that many Swift APIs are renamed in accordance with Swift 3 API design guidelines. Please refer to Swift Evolution document SE-0023, "API Design Guidelines."

这个文档描述了CoreData在 macOS 10.12, iOS 10.0,tvOS 10.0 和 watchOS 3.0的新功能。请注意有许多Swift的API 根据Swift 3 API 设计指南进行了重命名。请参考 Swift 进化文档 SE-0023, ”API 设计指南“

Concurrency changes and connection pooling

并发变化和连接池

The NSPersistentStoreCoordinator now maintains a small connection pool that allows concurrent database operations for NSSQLiteStoreType persistent stores. An NSManagedObjectContext (that is not nested) can now fetch and fault concurrently with other peer NSManagedObjectContext instances. For persistent stores using WAL journal_mode (the default in Core Data), the NSPersistentStoreCoordinator also supports 1 writer concurrently with multiple readers. For example, a UI context can fetch data concurrently with a single background context importing changes. Connection pooling uses less memory and generally out performs multiple separate NSPersistentStoreCoordinator instances to the same file.

NSPersistentStoreCoordinator(持久化协调者) 现在维持了一个小连接池,来NSSQLiteSToreType持久化进行并发数据操作。一个NSManagedObjectContext(对象上下文)和它对等的NSManagedObjectContext实例可以马上取数据和让并发失效。CoreData持久化默认使用的是WAL journal_mode, NSPersistentStoreCoordinator也支持1个写入者和多个读取者并发。举个例子:一个后台上下文在载入改变 ,同时一个界面上下文在读取数据。 对于同一个文件,连接池会使用较少的内存,多个NSPersistentStoreCoordinator实例对象通常都会分开执行。

This behavior is enabled for all existing Core Data clients. The default number of connections varies by platform but is greater than 1. You can adjust the behavior with the NSPersistentStoreConnectionPoolMaxSizeKey in your options dictionary when adding the store to the coordinator. NSPersistentStoreCoordinator briefly dispatches requests through its own queue, and custom code in blocks passed to NSPersistentStoreCoordinator.perform or NSPersistentStoreCoordinator.performAndWait will block the NSPersistentStoreCoordinator from routing future requests until they complete. Nested NSManagedObjectContext instances still serialize requests against their parent context as before.

在已经存在CoreData的客户端 这种行为是允许的。默认连接数量根据平台而异,但都是大于1。你在添加存储协调者的时候可以配置NSPersistentStoreConnectionPoolMaxSizeKey来调整行为。NSPersistentStoreCoordinator通过它的队列可以对所有请求短暂的分派,也可以通过NSPersistentStoreCoordinator.perform或者NSPersistentStoreCoordinator.performAndWait编写自定义代码,完成以后回调到指定的方法或Block代码块。嵌套的NSManagedObjectContext实例依旧针对父上下文保持连续请求。

NSPersistentContainer

持久容器

NSPersistentContainer is a new class that simplifies creating a new Core Data stack. It maintains references to your NSManagedObjectModel, NSPersistentStoreCoordinator, and other resources. NSPersistentContainer uses a new class NSPersistentStoreDescription to describe the configuration information to pass to NSPersistentStoreCoordinator when adding a persistent store. NSPersistentStoreDescription defaults to an NSSQLiteStoreType with automatic light weight migration enabled. The Xcode new project assistant for creating new iOS projects (but not macOS) that use Core Data now uses NSPersistentContainer in the AppDelegate. An example:

NSPersistentContainer是一个新类,它简化了创建一个心的CoreData堆。它维持了你项目中的NSManagedObjectModel ,NSPersistentStoreCoordinator 和其他资源的引用。在添加一个持久化存储的时候,NSPersistentContainer使用了一个新类NSPersistentStoreDescription来描述配置信息,并传到NSPersistentStoreCoordinator。NSPersistentStoreCoordinator默认可以自动对一个NSSQLiteStoreType进行迁移。在Xcode中新建iOS项目中,使用CoreData现在在AppDelegate中使用

NSPersistentContainer,示例如下:

let container = NSPersistentContainer(name: "myAppName")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
container.viewContext.perform({
// actions upon the NSMainQueueConcurrencyType NSManagedObjectContext for this container
})
})

  

This will find a model resource in the main bundle named after "myAppName", load it, create a new NSPersistentStoreCoordinator, and add a persistent store with the same name in the defaultDirectoryURL. The configuration details can be changed on the NSPersistentContainer before calling loadPersistentStores.

这个代码会在MainBundle资源库中找到一个名为”myAppName“的模型资源,加载它,创建一个新的NSPersistentStoreCoordinator持久化协调者,并在defaultDirectoryURL 这个默认路径下创建一个同名的持久化仓库。在还没有执行loadPersistentStores方法前,NSPersistentContainer持久化容器的配置是可以改变的。

NSPersistentContainer also has a few amenities for working with NSManagedObjectContext instances, including a single main queue context suitable for use with the view layer and factory methods for background contexts. You can also just give a block to the NSPersistentContainer which will asynchronously complete the task.

NSPersistentContainer持久化容器也给NSManagedObjectContext提供了一些便利的东西,包括在主线程队列中配合视图层和后台的方法使用,也可以在给一个Block异步调用。

let container = NSPersistentContainer.persistentContainerWithName("myApp")
container.performBackgroundTask() { (moc) in
// use moc to do asynchronous work
}

  

Query generations for transient versioning

瞬态多版本中的查询生成者

Core Data now supports pinning an NSManagedObjectContext to a specific query generation (database transaction) for arbitrarily many operations. A new class NSQueryGenerationToken represents an object that can be used to specify a pinning behavior or a specific version from another context. You can ask a context for its current queryGenerationToken or set one with setQueryGenerationFromToken(:) A nil token represents unpinned, which is the default behavior. Unpinned is the same NSManagedObjectContext behavior as previous releases. currentQueryGenerationToken is a token that can be passed to a context to tell it to lazily retrieve the most recent version on its next read operation (fetching or faulting) and then pin itself to that point in time. Calling save(), reset(), mergeChangesFromContextDidSaveNotification:, or mergeChangesFromRemoteContextSave(:intoContexts:) on any pinned context will automatically advance it to the most recent version for the operation and then reset its query generation to currentQueryGenerationToken.

The persistent store must be an NSSQLiteStoreType in WAL journal_mode (the default). Query generations expire if no contexts refer to them or the process terminates.

As an example:

对于许多反复无常的操作,CoreData现在支持针对一个特殊的查询生成对象(数据库事务)阻塞一个 NSManagedObjectContext ,一个新类NSQueryGenerationToken表示一个对象能在一个特殊的阻塞行为或者一个其他上下稳重特殊版本中被使用。你可以给当前queryGenerationToken或者调用setQueryGenerationFromToken(:) 设置一个token来请求一个上下文。默认nil表示没有绑定的。去除绑定和先前NSManagedObjectContext行为释放一样。currentQueryGenerationToke是一个可以通过一个上下文的令牌,并在告诉它在最近的一个版本在读取操作(读取或断开)的时候延迟得到最近的版本对象,然后及时的自己绑定。在任何已经绑定的上下文中请求save(), reset(), mergeChangesFromContextDidSaveNotification:, 或者 mergeChangesFromRemoteContextSave(:intoContexts:) 将会自动推荐最近版本的操作,然后重置currentQueryGenerationToken.

这个持久化仓库必须是一个基于 WAL journal_mode 的一个 NSSQLiteStoreType. 如果这些查询生成者不属于任何一个上下文或者他们在过程中终止,他们就会失效终止。

例如:

try container.viewContext.setQueryGenerationFromToken(NSQueryGenerationToken.currentQueryGenerationToken)
let request = NSFetchRequest(entityName:"Animal")
request.fetchBatchSize = 10
let results = try container.viewContext.executeFetchRequest(request)
let first = results.first
var aname = first.name // pull in the first batch's row data let moc = container.newBackgroundContext moc.performBlockAndWait() {
let update = NSBatchUpdateRequest(entityName:"Animal")
update.resultsType = .UpdatedObjectsCountResultType
update.propertiesToUpdate = ["name" : NSExpression(forConstantValue:"Cat")]
do {
let result = try moc.executeRequest(update)
} catch {
print("Error executing update: \(error)")
}
} var next = results[100]
aname = next.name // new reads from the batched fetch result still pull the previous verison's data try container.viewContainer.setQueryGenerationFromToken(NSQueryGenerationToken.currentQueryGenerationToken) next = results[200]
aname = next.name //now new reads from the batching result pull in the new Cat data

 

Managed Objects and subclassing

托管的对象和子类

If there is a 1:1 mapping between NSEntityDescription instances and custom NSManagedObject subclasses defined in your data model, Core Data will provide strongly typed conveniences on NSManagedObject subclasses in lieu of the string based NSEntityDescription class methods. These include the following new methods on NSManagedObject:

如果在你数据模型中,在NSEntityDescription 实例和自定义的NSManagedObject子类之间有一对一的对应映射关系,Core Data将在NSManagedObject子类中提供强类型的便利 来替代基于字符串的 NSEntityDescription类方法。在NSManagedObject中包含如下方法:

public class func entity() -> NSEntityDescription
public class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult>
public convenience init(context moc: NSManagedObjectContext)

  

The binding between entities and subclasses happens when the NSManagedObjectModel is first used to initialize an NSPersistentStoreCoordinator. If the mapping between NSEntityDescription instances and subclasses is ambiguous, the functionality is disabled. You should avoid creating new copies of the same NSManagedObjectModel by reloading it from disk repeatedly.

当NSManagedObjectModel(托管数据模型) 第一次使用NSPersistentStoreCoordinator (持久化协调者)的时候,就会将所有实体和所有子类进行绑定。如果NSEntityDescription实例和子类之间映射有歧义的话,函数是不可用的。你应该避免相同的NSManagedObjectModel在加载的时候反复从磁盘中创建新的复制版本。

Fetch Requests

读取请求

NSFetchRequest is now a parameterized type based on a new NSFetchRequestResult protocol. Several Core Data APIs now refer to the parameterized NSFetchRequest in both Objective-C and Swift.

NSFetchRequest是基于一个新的NSRetchRequestResult 协议的参数化类型。 几个CoreData API方法,参考OC和Swift 参数化类型的NSFetchRequest

Additionally in Swift, NSManagedObjectContext offers parameterized variants of fetch(:), the Swift 3 name for executeFetchRequest:error:, and count(:).

此外在Swift中,NSManagedObjectContext存在参数化变体 fetch(:) 和 count(:) ,  executeFetchRequest:error:在Swift 3中的命名

public func fetch<T : NSFetchRequestResult>(_ request: NSFetchRequest<T>) throws -> [T]
public func count<T : NSFetchRequestResult>(for request: NSFetchRequest<T>) throws -> Int

  

Bringing these changes together, in Swift 2 you might have had something like:

一起带来这些改变,在Swift 2 中可能有像这样的一些东西:

func findAnimals() {
let request = NSFetchRequest(entityName:”Animal")
do {
guard let searchResults = try context.executeFetchRequest(request) as? [Animal] else {
print("Results were not of the expected structure")
}
... use(searchResults) ...
} catch {
print("Error ocurred during execution: \(error)")
}
}

  

and in Swift 3:

在Swift 3中:

func findAnimals() {
let request: NSFetchRequest<Animal> = Animal.fetchRequest
do {
let searchResults = try context.fetch(request)
... use(searchResults) ...
} catch {
print("Error with request: \(error)")
}
}

  

NSFetchRequest also offers a new method execute() which can only be called within the scope of an NSManagedObjectContext instance's perform or performAndWait block's lexical scope. execute() directs that NSManagedObjectContext to execute the fetch request like:

NSFetchRequest 提供了一个新的方法 execute() , 但是它只能在NSManagedObjectContext 实例的 perform 或者 performAndWait 的Block(闭包)作用域中使用,使用示例如下:

func findAnimals() {
context.performAndWait({
let request : NSFetchRequest<Animal> = Animal.fetchRequest
do {
let searchResults = try request.execute()
... use(searchResults) ...
} catch {
print("Error with request: \(error)")
}
})
}

  

NSFetchedResultsController

查询结果控制器

The NSFetchedResultsController is now available on macOS 10.12. As with NSFetchRequest, it has become a parameterized type which it carries through to collections and methods derived from the NSFetchRequest that defines it.

NSFetchedResultsController目前只在 macOS 10.12 上可用。(未完待续。。。)

Xcode automatic subclass generation

Xcode now supports automatic generation of NSManagedObject subclasses in the modeling tool. In the entity inspector:

  • Manual/None is the default, and previous behavior; in this case you should implement your own subclass or use NSManagedObject.
  • Category/Extension generates a class extension in a file named like ClassName+CoreDataGeneratedProperties. You need to declare/implement the main class (if in Obj-C, via a header the extension can import named ClassName.h).
  • Class Definition generates subclass files named like ClassName+CoreDataClass as well as the files generated for Category/Extension.

The generated files are placed in DerivedData and rebuilt on the first build after the model is saved. They are also indexed by Xcode, so command-clicking on references and fast-opening by filename works.

Core Data iCloud Deprecation

As of macOS v10.12 and iOS 10.0; Core Data's iCloud integration feature has been deprecated. Apps will continue to work. There are no changes to or removal of the functionality in macOS 10.12 and iOS 10. Historically, deprecated symbols in Cocoa remain functional for a considerable period of time before removal. Only the client side Core Data iCloud API symbols are deprecated. Core Data with iCloud is built on top of the iCloud Drive service. The service pieces are not effected in any way. If and when the deprecated APIs are disabled in some future OS version, applications running on iOS 9 or 10 will continue to work.

Miscellaneous new API

  • NSManagedObjectContext now provides a property automaticallyMergesChangesFromParent that causes it to automatically register as an observer of NSManagedObjectContextDidSaveNotification posted by its parent store and call one of the mergeChanges methods upon itself.
  • NSPersistentStoreCoordinator provides a new addPersistentStoreWithDescription(:completionHandler:) method that takes an NSPersistentStoreDescription and uses it to call, optionally asynchronously, addPersistentStoreWithType:configuration:URL:options:error:.

Behavioral changes

Core Data has changed two behaviors for applications built with a minimum deployment target of macOS 10.12, iOS 10.0, tvOS 10.0, or watchOS 3.0.

  • performBlockAndWait: implicitly includes an autorelease pool around each block. Projects using ARC or Swift should be generally unaffected, although remember that both NSError** out parameters and exceptions are autoreleased and do not escape block lexical scope happily. Projects using manual retain / release will need to retain autoreleased objects, including the results of executeFetchRequest:error: inside the block and release or autorelease them outside the block's lexical scope. For example:
__block id result = nil;
[context performBlockAndWait:^{
NSError* error = nil;
result = [context executeFetchRequest:request error:&error];
}];
return result;

  

This code works under ARC but under manual retain release must instead be:

__block id result = nil;
[context performBlockAndWait:^{
NSError* error = nil;
result = [[context executeFetchRequest:request error:&error] retain];
}];
return [result autorelease];

  

    • NSManagedObjectContext now defaults to a nil NSUndoManager on macOS. It always defaulted to nil on iOS.
    • NSFetchedResultsController now correctly merges changes from other context for objects it hasn’t seen in its own context
    • NSFetchRequest now allows predicates to specify an entity restriction allowing fetches against entity hierarchies in which only some sub entities have the relevant property such as:
    • @“self.entity = %@ and subentityProperty = %@“ or even @“relationship.entity = %@ and relationship.onlysomedestinationsubentitiesAttribute = %@“
      
      Only one restricting entity qualifier per clause is allowed.
      
    • Core Data has adopted the new logging infrastructure in 10.12 and iOS 10.0, and switched from using NSLog to os_log with the logging subsystem "com.apple.coredata". The output of this logging can be viewed in the Console application, or in terminal with the command:
    • log stream —predicate 'subsystem = "com.apple.coredata"'
      
      As part of this transition, Core Data honors user defaults to log to os_log, stderr, or both with ‘com.apple.CoreData.Logging.oslog’ or ‘com.apple.CoreData.Logging.stderr’. Due to a known issue in Xcode, it may be useful to toggle stderr logging on during debugging.
      

        

    • NSManagedObject dynamic accessor generation has fixed issues to properly generate accessors for ordered to-many relationships. Core Data will generate any of the “Mutable Indexed Accessors” documented in Key-Value Coding Accessor Methods. Both ordered and unordered to-many relationships support all of the “Mutable Unordered Accessors” except intersection<Key>.The potentially generated accessors include a getter named exactly as the property name from the data model, or the following list where * is the capitalized property name:
      • set*:
      • primitive*
      • setPrimitive*:
      • add*Object:
      • add*:
      • remove*Object:
      • remove*:
      • removeObjectFrom*AtIndex:
      • remove*AtIndexes:
      • remove*:
      • insertObject: in*AtIndex:
      • insert*: AtIndexes:
      • replaceObjectIn*AtIndex: withObject:
      • replace*AtIndexes: with*:
      • validate*: error:
      • willChange*
      • didChange*
      • willAccess*
      • didAccess*
    • NSManagedObject will now also allow subclasses to override accessors and still invoke the implementation that otherwise would have been dynamically generated. This can be done by invoking a method named identically to the overridden method with ‘managedObjectOriginal_’ prepended. For example:

 

- (void)setDepartment:(Department *)value
{
// invoke the dynamic implementation of setDepartment
[self managedObjectOriginal_setDepartment:value]; NSLog(@"invoked %@", NSStringFromSelector(_cmd));
}

  

iOS10 CoreData新特性的更多相关文章

  1. ios9和ios10的新特性

    昨天面试了一个做ios开发的公司,其中面试官问我最新的ios系统版本是多少,以及它的特性是什么?由于自己是初学者,所以对这些没有关注过.今天特地搜索了一下关于ios9和ios10的新特性,并整理了一下 ...

  2. xCode8以及iOS10 的新特性

    其他:ios10中 适配问题(1.系统判断方法失效:2.隐私数据的访问问题:3.UIColor 问题4.真彩色的显示5.ATS问题6.UIStatusBar问题7.UITextField8.UserN ...

  3. iOS10新特性之CallKit开发详解:锁屏接听和来电识别

    国庆节过完了,回家好好休息一天,今天好好分享一下CallKit开发.最近发现好多吃瓜问CallKit的VoIP开发适配,对iOS10的新特性开发和适配也在上个月完成,接下来就分享一下VoIP应用如何使 ...

  4. iOS10新特性之SiriKit

    在6月14日凌晨的WWDC2016大会上,苹果提出iOS10是一次里程碑并且推出了十个新特性,大部分的特性是基于iPhone自身的原生应用的更新,具体的特性笔者不在这里再次叙述,请看客们移步WWDC2 ...

  5. iOS10 新特性-新功能,以及ReplayKit库

    iOS的10.0 本文总结了iOS的10,运行于目前推出iOS设备推出的主要开发者相关的功能. iOS版10引入了新的方法来增加您的应用程序通过帮助系统参与在适当的时候建议你的应用程序给用户.如果你在 ...

  6. Xcode8新特性和iOS10新特性

    从 Xcode 8.0 开始,目前所有的插件都无法工作! NSLog 无法输出 -- 此bug等待正式版本... Xcode 提供了文档注释快捷键option + cmd + / 但是要把系统升级到1 ...

  7. iOS10 新特性一

    链接:http://www.jianshu.com/p/0cc7aad638d9 1.Notification(通知) 自从Notification被引入之后,苹果就不断的更新优化,但这些更新优化只是 ...

  8. Xcode8 带来的新特性和坑

    Xcode8新特性 Interface Builder 随着14年的iPhone6和6P出来之后,iPhone的屏幕尺寸也越来越多,屏幕适配是一个需要解决的问题,以后不一定苹果又出什么尺寸的iPhon ...

  9. iOS UICollection 和UITableview新特性

    很详细优秀的博客: http://www.jianshu.com/p/e97780a24224 iOS10新特性总结 http://blog.csdn.net/yyacheng/article/det ...

随机推荐

  1. 数据库知识整理<二>

    又继续写的博客,希望自己能坚持每天写博客.分享自己的点滴,对自己成长有帮助.今天下午高强度打了三个小时篮球,小腿都抽筋了.很爽,失落的心情似乎变得开明了一些.想到了一句话:“像SB式的坚持总会有好的收 ...

  2. Javac不是内部或外部指令

    JDK安装完,命令行窗口中运行Java正常,运行Javac显示不是内部或外部指令 不存在百度上说的没有安装JDK,只安装了JRE 我的电脑是64位Win7操作系统 第一次安装的JDK不是从官网下载的, ...

  3. C++混合编程之idlcpp教程Lua篇(5)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(4) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程LuaTutorial3中,同样加入了三个文件:LuaTutori ...

  4. [Hyper-V]使用操作系统模板创建新的虚拟机

    描述: 为了节省空间和时间的目的,先在Hyper-V里创建一个干净的操作系统,以后再创建虚拟机时都基于此操作系统,节省了安装Windows的时间 另外创建其它虚拟机的时候,也以上述虚拟机的磁盘为基础盘 ...

  5. javascript跨域通信(一):利用location.hash实现跨域iframe自适应

    页面域关系: a.html所属域A:www.A.comb.html所属域B:www.B.com 问题本质: js对跨域iframe访问问题,因为要控制a.html中iframe的高度和宽度就必须首先读 ...

  6. ActiveMQ第四弹:在HermesJMS中创建ActiveMQ Session

    Hermes JMS是一个开源免费的跨平台的JMS消息监听工具.它可以很方便和各种JMS框架集成和交互,可以用来监听.发送.接收.修改.存储消息等.这篇文章将讲解HermesJMS如何集成Active ...

  7. Java中的Set, List, Map漫谈

    在编程语言中,集合是指代表一组对象的对象.Java平台专门有一个集合框架(Collections Framework).集合框架是指表示和操作集合的统一架构,隔离了集合的操作和实现细节. 集合框架中的 ...

  8. paip.函数式编程方法概述以及总结

    paip.函数式编程方法概述以及总结 1     函数式编程:函数式风格..很多命令式语言里支持函数式编程风格 1.1      起源 (图灵机,Lisp机器, 神经网络计算机) 1.2      函 ...

  9. iOS-SVN、Git

     版本控制SVN和Git使用详解     公司的实际开发中,在天朝使用较多的还是SVN,因为SVN是集中式的,在天朝上班你们都懂的!     -----------------svn--------- ...

  10. Alfred 使用简介

    1.安装(不说了去 Google 吧) 2.基础快捷键:option+space 3.打开应用程序:Alfred 几乎是一切程序的入口,你再也不需要找妈妈要开始菜单了.用快捷键呼出Alfred,输入任 ...