Swift Core Data 是 Apple 平台上的一个强大的数据持久化框架,它提供了对象-关系映射(ORM)功能,允许开发者以面向对象的方式管理和存储数据。Core Data 不仅支持将数据存储到本地磁盘,还提供了对象图管理、数据验证、撤销/重做等高级功能。
Core Data 的核心组件包括:
NSManagedObjectModel:表示应用的数据模型,包含实体(Entity)、属性(Attribute)和关系(Relationship)的定义。
NSPersistentStoreCoordinator:负责管理数据的存储和读取,处理不同类型的持久化存储(如 SQLite、XML、二进制文件等)。
NSManagedObjectContext:提供了一个工作空间,用于创建、读取、更新和删除托管对象。它跟踪对象的变化,并在需要时将这些变化保存到持久化存储中。
NSManagedObject:表示模型中的实体实例,是应用直接操作的数据对象。
Core Data 的工作流程通常包括以下步骤:
创建或加载托管对象模型。
创建持久化存储协调器并添加持久化存储。
创建托管对象上下文并将其与持久化存储协调器关联。
使用托管对象上下文执行数据操作(创建、读取、更新、删除)。
当需要保存更改时,调用托管对象上下文的 save()
方法。
下面我们将深入分析 Core Data 各组件的源码实现。
托管对象模型是 Core Data 的数据蓝图,它定义了应用的数据结构。在源码中,NSManagedObjectModel
类的核心实现如下:
@interface NSManagedObjectModel : NSObject
// 初始化方法,从URL加载模型
- (instancetype)initWithContentsOfURL:(NSURL *)modelURL;
// 获取模型中的所有实体
@property (readonly, copy) NSArray *entities;
// 根据名称获取实体
- (NSEntityDescription *)entityForName:(NSString *)entityName;
// 模型的版本信息
@property (readonly, copy) NSString *versionHashModifier;
@property (readonly, copy) NSDictionary *versionHashesByName;
@end
NSManagedObjectModel
的实现涉及以下几个关键部分:
实体管理:模型内部维护一个实体数组,每个实体由 NSEntityDescription
表示。
版本控制:Core Data 支持模型版本控制,通过 versionHashesByName
属性可以获取每个实体的版本哈希值。
加载机制:模型可以从 .momd
或 .mom
文件加载,这些文件是 Xcode 编译数据模型文件(.xcdatamodeld
)后生成的。
NSEntityDescription
类表示模型中的实体,其核心实现如下:
@interface NSEntityDescription : NSObject
// 实体名称
@property (nullable, copy) NSString *name;
// 实体的父实体(用于继承)
@property (nullable, strong) NSEntityDescription *superentity;
// 实体的属性和关系
@property (readonly, copy) NSArray *attributes;
@property (readonly, copy) NSArray *relationships;
// 实体对应的类名
@property (nullable, copy) NSString *managedObjectClassName;
// 创建实体的实例
- (NSManagedObject *)insertNewObjectIntoContext:(NSManagedObjectContext *)context;
@end
NSEntityDescription
负责定义实体的属性、关系和继承结构。每个实体可以有一个父实体,形成继承层次结构。
持久化存储协调器是 Core Data 的数据存储管理器,它的核心实现如下:
@interface NSPersistentStoreCoordinator : NSObject
// 初始化方法,传入托管对象模型
- (instancetype)initWithManagedObjectModel:(NSManagedObjectModel *)model;
// 托管对象模型
@property (readonly, strong) NSManagedObjectModel *managedObjectModel;
// 添加持久化存储
- (NSPersistentStore *)addPersistentStoreWithType:(NSString *)storeType
configuration:(nullable NSString *)configuration
URL:(nullable NSURL *)storeURL
options:(nullable NSDictionary *)options
error:(NSError **)error;
// 移除持久化存储
- (BOOL)removePersistentStore:(NSPersistentStore *)store error:(NSError **)error;
// 获取所有持久化存储
@property (readonly, copy) NSArray *persistentStores;
@end
NSPersistentStoreCoordinator
的实现涉及以下几个关键部分:
存储类型支持:Core Data 支持多种存储类型,包括 SQLite(NSSQLiteStoreType
)、XML(NSXMLStoreType
)、二进制(NSBinaryStoreType
)和内存(NSInMemoryStoreType
)。
存储管理:协调器维护一个持久化存储数组,每个存储由 NSPersistentStore
表示。
存储加载:addPersistentStoreWithType:
方法负责加载指定类型的存储,并将其与协调器关联。
NSPersistentStore
类是一个抽象基类,具体的存储类型由其子类实现。例如,SQLite 存储由 NSSQLCore
类实现,它继承自 NSPersistentStore
。
托管对象上下文是 Core Data 的工作horse,它的核心实现如下:
@interface NSManagedObjectContext : NSObject
// 初始化方法
- (instancetype)init;
- (instancetype)initWithConcurrencyType:(NSManagedObjectContextConcurrencyType)concurrencyType;
// 并发类型
@property (readonly) NSManagedObjectContextConcurrencyType concurrencyType;
// 持久化存储协调器
@property (nullable, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
// 父上下文(用于父子上下文架构)
@property (nullable, strong) NSManagedObjectContext *parentContext;
// 插入新对象
- (void)insertObject:(NSManagedObject *)object;
// 获取对象
- (nullable NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID;
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error;
// 删除对象
- (void)deleteObject:(NSManagedObject *)object;
// 保存更改
- (BOOL)save:(NSError **)error;
// 撤销/重做支持
@property (nullable, strong) NSUndoManager *undoManager;
- (void)undo;
- (void)redo;
// 注册通知
@property (class, readonly, copy) NSString *NSManagedObjectContextDidSaveNotification;
@property (class, readonly, copy) NSString *NSManagedObjectContextObjectsDidChangeNotification;
@end
NSManagedObjectContext
的实现涉及以下几个关键部分:
对象注册与跟踪:上下文维护一个注册表,记录所有被管理的对象及其状态(如新插入、已修改、已删除)。
变化管理:上下文跟踪对象的变化,并在调用 save()
方法时将这些变化持久化到存储中。
并发支持:上下文支持不同的并发类型(主队列、私有队列),通过 performBlock:
和 performBlockAndWait:
方法确保线程安全。
父子上下文架构:上下文可以有父子关系,形成层次结构,子上下文的变化可以逐级提交到父上下文,最终保存到持久化存储。
托管对象是 Core Data 中的数据对象,它的核心实现如下:
@interface NSManagedObject : NSObject
// 初始化方法
- (instancetype)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(nullable NSManagedObjectContext *)context;
// 实体描述
@property (readonly, strong) NSEntityDescription *entity;
// 托管对象上下文
@property (nullable, readonly, strong) NSManagedObjectContext *managedObjectContext;
// 对象ID
@property (readonly, strong) NSManagedObjectID *objectID;
// 对象状态
@property (readonly) NSManagedObjectState managedObjectState;
// 属性访问
- (id)valueForKey:(NSString *)key;
- (void)setValue:(id)value forKey:(NSString *)key;
// 验证方法
- (BOOL)validateForInsert:(NSError **)error;
- (BOOL)validateForUpdate:(NSError **)error;
- (BOOL)validateForDelete:(NSError **)error;
@end
NSManagedObject
的实现涉及以下几个关键部分:
动态属性访问:通过 valueForKey:
和 setValue:forKey:
方法实现动态属性访问,这些方法会根据实体描述动态查找和设置属性值。
对象状态管理:每个对象有一个状态(如 NSManagedObjectStateInserted
、NSManagedObjectStateUpdated
、NSManagedObjectStateDeleted
),上下文通过这些状态来跟踪对象的变化。
验证机制:提供验证方法,确保对象在插入、更新或删除前满足实体定义的约束条件。
Core Data 默认使用 SQLite 作为持久化存储,其实现涉及以下关键部分:
// NSSQLCore 类的部分实现,负责 SQLite 存储
@interface NSSQLCore : NSPersistentStore {
// SQLite 数据库连接
sqlite3 *_db;
// 缓存的 SQL 语句
NSMutableDictionary *_sqlCache;
// 数据库架构信息
NSSQLModel *_model;
// 其他成员变量...
}
// 打开数据库
- (BOOL)_openDatabase:(NSError **)error;
// 执行 SQL 语句
- (BOOL)_executeSQL:(NSString *)sql error:(NSError **)error;
// 执行查询并返回结果集
- (NSSQLRowCache *)_newRowsForFetchPlan:(NSSQLFetchRequestContext *)fetchPlan error:(NSError **)error;
@end
// NSSQLModel 类的部分实现,负责模型到 SQL 的映射
@interface NSSQLModel : NSObject {
// 实体到表的映射
NSMutableDictionary *_entitiesByName;
// 其他成员变量...
}
// 根据实体获取对应的表描述
- (NSSQLEntity *)entityForDescription:(NSEntityDescription *)entityDescription;
// 生成创建表的 SQL 语句
- (NSString *)_createTableStatementForEntity:(NSSQLEntity *)entity;
@end
// NSSQLGenerator 类的部分实现,负责生成 SQL 语句
@interface NSSQLGenerator : NSObject {
// 当前生成的 SQL 语句
NSMutableString *_sqlString;
// 其他成员变量...
}
// 生成插入语句
- (NSString *)generateInsertStatementForRow:(NSSQLRow *)row;
// 生成查询语句
- (NSString *)generateSelectStatementForFetchRequest:(NSFetchRequest *)request;
// 生成更新语句
- (NSString *)generateUpdateStatementForRow:(NSSQLRow *)row withOriginalRow:(NSSQLRow *)originalRow;
// 生成删除语句
- (NSString *)generateDeleteStatementForRow:(NSSQLRow *)row;
@end
除了 SQLite,Core Data 还支持其他存储类型:
XML 存储:将数据以 XML 格式存储,适合小型数据和调试。
二进制存储:将数据以二进制格式存储,读写效率较高。
内存存储:将数据存储在内存中,适合临时数据和测试。
这些存储类型的实现与 SQLite 存储类似,但在数据格式和读写方式上有所不同。
当数据模型发生变化时,Core Data 提供了迁移机制。迁移过程涉及源模型、目标模型和映射模型。
// NSMappingModel 类的部分实现,负责模型迁移映射
@interface NSMappingModel : NSObject {
// 源模型和目标模型
NSManagedObjectModel *_sourceModel;
NSManagedObjectModel *_destinationModel;
// 实体映射
NSArray *_entityMappings;
// 其他成员变量...
}
// 创建映射模型
+ (nullable instancetype)mappingModelFromBundles:(nullable NSArray *)bundles forSourceModel:(NSManagedObjectModel *)sourceModel destinationModel:(NSManagedObjectModel *)destinationModel;
// 执行迁移
- (BOOL)migrateStoreFromURL:(NSURL *)sourceURL
type:(NSString *)sourceStoreType
options:(nullable NSDictionary *)sourceOptions
withMappingModel:(nullable NSMappingModel *)mappingModel
toDestinationURL:(NSURL *)destinationURL
destinationType:(NSString *)destinationStoreType
destinationOptions:(nullable NSDictionary *)destinationOptions
error:(NSError **)error;
@end
轻量级迁移是 Core Data 提供的一种自动迁移机制,适用于简单的模型变化:
// 轻量级迁移选项
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption: @YES,
NSInferMappingModelAutomaticallyOption: @YES
};
// 添加持久化存储时使用这些选项
NSError *error = nil;
NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error];
NSFetchRequest 是 Core Data 中用于查询数据的核心类,其实现涉及以下关键部分:
@interface NSFetchRequest : NSObject
// 初始化方法
+ (instancetype)fetchRequestWithEntityName:(NSString *)entityName;
// 查询的实体
@property (nullable, strong) NSEntityDescription *entity;
// 查询谓词
@property (nullable, strong) NSPredicate *predicate;
// 排序描述符
@property (nullable, copy) NSArray *sortDescriptors;
// 结果限制
@property NSInteger fetchLimit;
@property NSInteger fetchOffset;
// 返回类型
@property NSFetchRequestResultType resultType;
// 执行查询
- (NSArray *)execute:(NSError **)error;
@end
NSFetchRequest
的实现涉及查询条件的构建、排序和分页的处理,以及查询结果的返回类型控制。
谓词是 Core Data 中用于定义查询条件的机制,其实现涉及多种谓词类型:
@interface NSPredicate : NSObject
// 创建谓词的工厂方法
+ (instancetype)predicateWithFormat:(NSString *)predicateFormat, ...;
+ (instancetype)predicateWithFormat:(NSString *)predicateFormat arguments:(va_list)argList;
+ (instancetype)predicateWithValue:(BOOL)value;
// 评估谓词
- (BOOL)evaluateWithObject:(id)object;
// 子类需要实现的方法
- (void)acceptVisitor:(id)visitor flags:(NSUInteger)flags;
@end
// 比较谓词
@interface NSComparisonPredicate : NSPredicate {
// 左侧表达式
NSExpression *_leftExpression;
// 右侧表达式
NSExpression *_rightExpression;
// 比较操作符
NSPredicateOperatorType _comparisonPredicateOperatorType;
// 其他成员变量...
}
@end
// 逻辑谓词
@interface NSCompoundPredicate : NSPredicate {
// 子谓词
NSArray *_subpredicates;
// 逻辑操作符(AND、OR、NOT)
NSCompoundPredicateType _compoundPredicateType;
// 其他成员变量...
}
@end
谓词的实现涉及表达式解析、逻辑运算和比较操作的处理。Core Data 使用谓词来过滤查询结果,确保只返回符合条件的数据。
Core Data 查询的执行流程涉及以下关键步骤:
请求验证:验证查询请求的有效性,确保实体、谓词等设置正确。
查询计划生成:根据查询请求和存储类型生成最优的查询计划。
SQL 生成:将查询请求转换为具体的 SQL 语句(对于 SQLite 存储)。
数据检索:执行 SQL 语句,从数据库中检索数据。
对象创建与缓存:根据检索到的数据创建托管对象,并进行缓存。
下面是查询执行的部分源码实现:
// NSManagedObjectContext 中执行查询的方法
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error {
// 验证请求
if (![self _validateFetchRequest:request error:error]) {
return nil;
}
// 创建查询上下文
NSFetchRequestContext *fetchContext = [[NSFetchRequestContext alloc] initWithFetchRequest:request context:self];
// 执行查询计划
id result = [self.persistentStoreCoordinator executeRequest:request withContext:self error:error];
if (result == nil) {
return nil;
}
// 处理查询结果
return [self _processFetchResult:result forRequest:request context:fetchContext error:error];
}
// NSPersistentStoreCoordinator 中执行查询的方法
- (id)executeRequest:(NSPersistentStoreRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)error {
// 根据请求类型选择合适的存储执行请求
if ([request isKindOfClass:[NSFetchRequest class]]) {
NSFetchRequest *fetchRequest = (NSFetchRequest *)request;
// 确定使用哪个存储执行查询
NSPersistentStore *store = [self _storeForEntity:fetchRequest.entity];
if (!store) {
if (error) *error = [NSError errorWithDomain:NSPersistentStoreCoordinatorErrorDomain code:NSPersistentStoreIncompatibleVersionHashError userInfo:nil];
return nil;
}
// 在存储上执行查询
return [store executeRequest:request withContext:context error:error];
}
// 处理其他类型的请求...
return nil;
}
// NSSQLCore(SQLite 存储)中执行查询的方法
- (id)executeRequest:(NSPersistentStoreRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)error {
if ([request isKindOfClass:[NSFetchRequest class]]) {
NSFetchRequest *fetchRequest = (NSFetchRequest *)request;
// 生成 SQL 查询语句
NSString *sql = [self _generateSQLForFetchRequest:fetchRequest];
// 执行 SQL 查询
sqlite3_stmt *stmt;
int result = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &stmt, NULL);
if (result != SQLITE_OK) {
if (error) *error = [NSError errorWithDomain:NSSQLiteErrorDomain code:result userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"SQLite error: %s", sqlite3_errmsg(_db)]}];
return nil;
}
// 处理查询结果
NSMutableArray *results = [NSMutableArray array];
while (sqlite3_step(stmt) == SQLITE_ROW) {
// 从结果集中提取数据
id object = [self _objectFromResultSet:stmt forEntity:fetchRequest.entity];
// 如果对象已存在于上下文中,则使用上下文中的实例
if ([context registeredObjectForID:[object objectID]]) {
object = [context objectWithID:[object objectID]];
} else {
// 注册新对象
[context _registerObject:object];
}
[results addObject:object];
}
sqlite3_finalize(stmt);
return results;
}
// 处理其他类型的请求...
return nil;
}
Core Data 的变化跟踪机制涉及以下关键部分:
NSManagedObject.h
中:typedef NS_ENUM(NSUInteger, NSManagedObjectState) {
NSManagedObjectStateTransient, // 临时状态,刚创建但未插入上下文
NSManagedObjectStatePending, // 已插入上下文但未保存
NSManagedObjectStateInserted, // 已插入且未保存
NSManagedObjectStateUpdated, // 已修改且未保存
NSManagedObjectStateDeleted, // 已删除且未保存
NSManagedObjectStateRefreshed, // 已刷新
NSManagedObjectStateFault // 未加载(故障状态)
};
// NSManagedObjectContext 中变化跟踪的部分实现
@interface NSManagedObjectContext () {
// 已插入的对象集合
NSMutableSet *_insertedObjects;
// 已修改的对象集合
NSMutableSet *_updatedObjects;
// 已删除的对象集合
NSMutableSet *_deletedObjects;
// 其他成员变量...
}
// 注册对象的插入
- (void)_registerInsertedObject:(NSManagedObject *)object;
// 注册对象的修改
- (void)_registerUpdatedObject:(NSManagedObject *)object;
// 注册对象的删除
- (void)_registerDeletedObject:(NSManagedObject *)object;
// 检查对象是否有未保存的变化
- (BOOL)_objectHasChanges:(NSManagedObject *)object;
@end
NSUndoManager
集成,支持撤销和重做操作:// NSManagedObjectContext 中撤销支持的部分实现
- (void)undo {
if (self.undoManager && [self.undoManager canUndo]) {
[self.undoManager undo];
}
}
- (void)redo {
if (self.undoManager && [self.undoManager canRedo]) {
[self.undoManager redo];
}
}
// 注册撤销操作
- (void)_registerUndoForOperation:(NSString *)operation withTarget:(id)target selector:(SEL)selector object:(id)object {
if (self.undoManager) {
[self.undoManager registerUndoWithTarget:target selector:selector object:object];
[self.undoManager setActionName:operation];
}
}
保存操作将上下文的变化持久化到存储中,其实现涉及以下关键部分:
// NSManagedObjectContext 中 save 方法的部分实现
- (BOOL)save:(NSError **)error {
// 检查是否有变化需要保存
if (![self hasChanges]) {
return YES;
}
// 验证所有变化的对象
if (![self _validateChangesForSave:error]) {
return NO;
}
// 开始事务
if (![self _beginTransaction:error]) {
return NO;
}
BOOL success = NO;
@try {
// 保存变化到持久化存储
if ([self.parentContext]) {
// 如果有父上下文,先将变化保存到父上下文
[self.parentContext performBlockAndWait:^{
success = [self.parentContext save:error];
}];
} else {
// 没有父上下文,直接保存到持久化存储
success = [self.persistentStoreCoordinator saveChanges:self error:error];
}
if (success) {
// 保存成功,清除变化记录
[self _clearChanges];
// 发送保存通知
[self _postSaveNotification];
}
}
@catch (NSException *exception) {
// 处理异常
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSManagedObjectContextSaveException userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Save failed: %@", [exception reason]]}];
}
success = NO;
}
@finally {
// 结束事务
[self _endTransaction];
}
return success;
}
// NSPersistentStoreCoordinator 中保存变化的方法
- (BOOL)saveChanges:(NSManagedObjectContext *)context error:(NSError **)error {
// 获取上下文中的变化
NSSet *insertedObjects = [context insertedObjects];
NSSet *updatedObjects = [context updatedObjects];
NSSet *deletedObjects = [context deletedObjects];
// 对每个存储执行保存操作
for (NSPersistentStore *store in self.persistentStores) {
// 筛选出属于该存储的对象
NSSet *storeInsertedObjects = [self _objectsInSet:insertedObjects forStore:store];
NSSet *storeUpdatedObjects = [self _objectsInSet:updatedObjects forStore:store];
NSSet *storeDeletedObjects = [self _objectsInSet:deletedObjects forStore:store];
// 在存储上执行保存
if (![store saveChangesToStore:storeInsertedObjects updatedObjects:storeUpdatedObjects deletedObjects:storeDeletedObjects withContext:context error:error]) {
return NO;
}
}
return YES;
}
// NSSQLCore(SQLite 存储)中保存变化的方法
- (BOOL)saveChangesToStore:(NSSet *)insertedObjects updatedObjects:(NSSet *)updatedObjects deletedObjects:(NSSet *)deletedObjects withContext:(NSManagedObjectContext *)context error:(NSError **)error {
// 开始 SQLite 事务
if (![self _beginSQLTransaction:error]) {
return NO;
}
BOOL success = YES;
@try {
// 处理删除的对象
for (NSManagedObject *object in deletedObjects) {
if (![self _deleteObject:object error:error]) {
success = NO;
break;
}
}
// 处理更新的对象
if (success) {
for (NSManagedObject *object in updatedObjects) {
if (![self _updateObject:object error:error]) {
success = NO;
break;
}
}
}
// 处理插入的对象
if (success) {
for (NSManagedObject *object in insertedObjects) {
if (![self _insertObject:object error:error]) {
success = NO;
break;
}
}
}
// 提交事务
if (success) {
if (![self _commitSQLTransaction:error]) {
success = NO;
}
} else {
// 回滚事务
[self _rollbackSQLTransaction];
}
}
@catch (NSException *exception) {
// 处理异常
if (error) {
*error = [NSError errorWithDomain:NSSQLiteErrorDomain code:NSInternalInconsistencyException userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Save failed: %@", [exception reason]]}];
}
success = NO;
[self _rollbackSQLTransaction];
}
return success;
}
当多个上下文同时修改同一数据时,可能会发生冲突,Core Data 提供了冲突解决机制:
// NSManagedObjectContext 中冲突解决的部分实现
- (BOOL)_resolveConflicts:(NSArray *)conflicts error:(NSError **)error {
// 如果没有设置冲突解决策略,使用默认策略
NSMergePolicyType mergePolicyType = self.mergePolicy.mergeType;
for (NSMergeConflict *conflict in conflicts) {
BOOL resolved = NO;
switch (mergePolicyType) {
case NSMergeByPropertyStoreTrumpMergePolicyType:
// 属性存储胜出策略:使用存储中的值覆盖内存中的值
resolved = [self _resolveConflict:conflict usingStoreTrumpPolicy];
break;
case NSMergeByPropertyObjectTrumpMergePolicyType:
// 属性对象胜出策略:使用内存中的值覆盖存储中的值
resolved = [self _resolveConflict:conflict usingObjectTrumpPolicy];
break;
case NSOverwriteMergePolicyType:
// 覆盖策略:直接用当前上下文的值覆盖存储中的值
resolved = [self _resolveConflict:conflict usingOverwritePolicy];
break;
case ABORT:
// 中止策略:不解决冲突,抛出错误
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSManagedObjectContextMergeConflictError userInfo:@{NSMergeConflictsKey: @[conflict]}];
}
return NO;
default:
// 自定义策略
resolved = [self.mergePolicy resolveConflict:conflict error:error];
break;
}
if (!resolved) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSManagedObjectContextMergeConflictError userInfo:@{NSMergeConflictsKey: @[conflict]}];
}
return NO;
}
}
return YES;
}
Core Data 的上下文不是线程安全的,其源码实现中涉及以下线程安全机制:
// NSManagedObjectContext 中并发控制的部分实现
@interface NSManagedObjectContext () {
// 并发队列
dispatch_queue_t _queue;
// 并发类型
NSManagedObjectContextConcurrencyType _concurrencyType;
// 其他成员变量...
}
// 在上下文的队列上执行块
- (void)performBlock:(void (^)(void))block;
- (void)performBlockAndWait:(void (^)(void))block;
// 验证当前是否在正确的线程/队列上执行
- (BOOL)_isValidThreadForOperation;
- (void)_enforceReadOnly;
- (void)_enforceReadWrite;
@end
// performBlock 方法的实现
- (void)performBlock:(void (^)(void))block {
if (!block) return;
if (_concurrencyType == NSMainQueueConcurrencyType) {
dispatch_async(dispatch_get_main_queue(), block);
} else {
dispatch_async(_queue, block);
}
}
// performBlockAndWait 方法的实现
- (void)performBlockAndWait:(void (^)(void))block {
if (!block) return;
if (_concurrencyType == NSMainQueueConcurrencyType) {
if ([NSThread isMainThread]) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
} else {
dispatch_sync(_queue, block);
}
}
为了在多线程环境中使用 Core Data,通常采用多上下文架构:
// 创建父子上下文架构的示例代码
- (void)setupCoreDataStack {
// 创建主上下文,与主线程关联
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
// 创建私有上下文,用于后台操作
_privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_privateContext.parentContext = _mainContext;
// 监听保存通知,确保上下文之间的数据同步
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:_privateContext];
}
// 处理保存通知的方法
- (void)contextDidSave:(NSNotification *)notification {
// 确保在主上下文的队列上执行
[_mainContext performBlock:^{
// 合并变化
[_mainContext mergeChangesFromContextDidSaveNotification:notification];
// 保存主上下文到持久化存储
NSError *error = nil;
if (![_mainContext save:&error]) {
NSLog(@"Error saving main context: %@", error);
}
}];
}
Core Data 提供了多种跨线程通信机制:
使用 performBlock 和 performBlockAndWait:
使用对象 ID:
objectID
在不同上下文之间引用同一对象:// 在后台线程获取对象 ID
NSManagedObjectID *objectID = [managedObject objectID];
// 在主线程通过对象 ID 获取对象
[_mainContext performBlock:^{
NSManagedObject *object = [_mainContext objectWithID:objectID];
// 使用对象...
}];
NSManagedObjectContextDidSaveNotification
通知其他上下文有变化发生:// 注册通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
// 处理通知
- (void)contextDidSave:(NSNotification *)notification {
// 合并变化
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
Core Data 实现了对象缓存机制,确保同一对象在同一上下文中只有一个实例:
// NSManagedObjectContext 中对象缓存的部分实现
@interface NSManagedObjectContext () {
// 对象缓存
NSMutableDictionary *_objectCache;
// 对象 ID 到对象的映射
NSMutableDictionary *_objectIDsToObjects;
// 其他成员变量...
}
// 注册对象到缓存
- (void)_registerObject:(NSManagedObject *)object;
// 从缓存中获取对象
- (nullable NSManagedObject *)_objectForID:(NSManagedObjectID *)objectID;
// 从缓存中移除对象
- (void)_unregisterObject:(NSManagedObject *)object;
@end
// 注册对象到缓存的方法
- (void)_registerObject:(NSManagedObject *)object {
@synchronized(self) {
// 将对象添加到缓存
[_objectCache setObject:object forKey:[object objectID]];
// 如果对象是新插入的,记录其初始值
if (object.managedObjectState == NSManagedObjectStateInserted) {
[self _recordInitialValuesForObject:object];
}
}
}
// 从缓存中获取对象的方法
- (nullable NSManagedObject *)_objectForID:(NSManagedObjectID *)objectID {
@synchronized(self) {
return [_objectCache objectForKey:objectID];
}
}
Core Data 还实现了元数据缓存机制,提高模型加载和查询效率:
// NSManagedObjectModel 中缓存的部分实现
@interface NSManagedObjectModel () {
// 实体名称到实体的映射
NSMutableDictionary *_entitiesByName;
// 版本哈希缓存
NSMutableDictionary *_versionHashesByName;
// 其他成员变量...
}
// 从缓存中获取实体
- (nullable NSEntityDescription *)_entityByName:(NSString *)name;
// 计算并缓存版本哈希
- (NSData *)_versionHashForEntity:(NSEntityDescription *)entity;
@end
// NSPersistentStoreCoordinator 中缓存的部分实现
@interface NSPersistentStoreCoordinator () {
// 存储类型到存储类的映射
NSMutableDictionary *_storeTypeToClassMap;
// 存储 URL 到存储的映射
NSMutableDictionary *_storeURLToStoreMap;
// 其他成员变量...
}
// 从缓存中获取存储类
- (Class)_storeClassForType:(NSString *)storeType;
// 从缓存中获取存储
- (nullable NSPersistentStore *)_storeForURL:(NSURL *)storeURL;
@end
当内存不足时,Core Data 会执行缓存淘汰策略:
// NSManagedObjectContext 中缓存淘汰的部分实现
- (void)_evictObjectsIfNeeded {
// 检查内存使用情况
BOOL memoryPressure = [self _hasMemoryPressure];
if (memoryPressure) {
// 获取可以安全释放的对象
NSArray *objectsToEvict = [self _objectsToEvict];
// 释放对象
for (NSManagedObject *object in objectsToEvict) {
[self _evictObject:object];
}
}
}
// 获取可以安全释放的对象
- (NSArray *)_objectsToEvict {
NSMutableArray *objects = [NSMutableArray array];
// 遍历缓存中的对象
for (NSManagedObject *object in [_objectCache allValues]) {
// 只释放未被修改且未被引用的对象
if (object.managedObjectState == NSManagedObjectStateUnchanged &&
[object _referenceCount] == 1) {
[objects addObject:object];
}
}
// 根据访问时间排序,先释放最久未使用的对象
[objects sortUsingComparator:^NSComparisonResult(NSManagedObject *obj1, NSManagedObject *obj2) {
return [obj1 _lastAccessTime] compare:[obj2 _lastAccessTime];
}];
// 只返回一部分对象,避免释放过多
NSUInteger countToEvict = MIN(objects.count, [self _maxObjectsToEvict]);
return [objects subarrayWithRange:NSMakeRange(0, countToEvict)];
}
// 释放对象
- (void)_evictObject:(NSManagedObject *)object {
// 将对象转换为故障状态
[object _turnIntoFault];
// 从缓存中移除
[_objectCache removeObjectForKey:[object objectID]];
}
Core Data 提供了属性验证机制,确保数据的有效性:
// NSManagedObject 中属性验证的部分实现
@interface NSManagedObject ()
// 验证属性值
- (BOOL)_validateValue:(inout id *)ioValue forKey:(NSString *)key error:(NSError **)error;
// 子类可以重写的验证方法
- (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)key error:(NSError **)error;
- (BOOL)validateForInsert:(NSError **)error;
- (BOOL)validateForUpdate:(NSError **)error;
- (BOOL)validateForDelete:(NSError **)error;
@end
// 验证属性值的方法
- (BOOL)_validateValue:(inout id *)ioValue forKey:(NSString *)key error:(NSError **)error {
// 获取属性描述
NSAttributeDescription *attribute = [[self.entity attributesByName] objectForKey:key];
if (!attribute) {
// 如果不是属性,检查是否是关系
NSRelationshipDescription *relationship = [[self.entity relationshipsByName] objectForKey:key];
if (relationship) {
// 验证关系
return [self _validateRelationship:relationship value:ioValue error:error];
}
// 未知键
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSUndefinedKeyError userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Object %@ has no attribute or relationship named %@", self, key]}];
}
return NO;
}
// 验证属性类型
if (*ioValue != nil && ![self _isValidValue:*ioValue forAttribute:attribute]) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSValidationTypeError userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Value %@ is not of the correct type for attribute %@", *ioValue, key]}];
}
return NO;
}
// 验证属性是否可为空
if (*ioValue == nil && !attribute.allowsNull) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSValidationMissingMandatoryPropertyError userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Attribute %@ cannot be nil", key]}];
}
return NO;
}
// 调用子类的验证方法
return [self validateValue:ioValue forKey:key error:error];
}
除了属性验证,Core Data 还支持关系验证:
// NSManagedObject 中关系验证的部分实现
- (BOOL)_validateRelationship:(NSRelationshipDescription *)relationship value:(inout id *)ioValue error:(NSError **)error {
// 验证关系类型
if (*ioValue != nil) {
if (relationship.toMany) {
// 多对多或一对多关系,值必须是集合
if (![*ioValue isKindOfClass:[NSSet class]] && ![*ioValue isKindOfClass:[NSOrderedSet class]]) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSValidationTypeError userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Value %@ is not a valid collection type for to-many relationship %@", *ioValue, relationship.name]}];
}
return NO;
}
// 验证集合中的每个对象
for (id object in (NSFastEnumeration *)*ioValue) {
if (![object isKindOfClass:[NSManagedObject class]] ||
![object.entity isSubentityOfEntity:relationship.destinationEntity]) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSValidationTypeError userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Object %@ is not of the correct type for relationship %@", object, relationship.name]}];
}
return NO;
}
}
} else {
// 一对一关系,值必须是单个对象
if (![*ioValue isKindOfClass:[NSManagedObject class]] ||
![(*ioValue).entity isSubentityOfEntity:relationship.destinationEntity]) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSValidationTypeError userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Object %@ is not of the correct type for relationship %@", *ioValue, relationship.name]}];
}
return NO;
}
}
}
// 验证反向关系的一致性
if (relationship.inverseRelationship) {
return [self _validateInverseRelationship:relationship value:ioValue error:error];
}
return YES;
}
Core Data 的验证流程涉及以下关键步骤:
// NSManagedObjectContext 中验证的部分实现
- (BOOL)_validateChangesForSave:(NSError **)error {
// 验证插入的对象
for (NSManagedObject *object in [self insertedObjects]) {
if (![object validateForInsert:error]) {
return NO;
}
}
// 验证更新的对象
for (NSManagedObject *object in [self updatedObjects]) {
if (![object validateForUpdate:error]) {
return NO;
}
}
// 验证删除的对象
for (NSManagedObject *object in [self deletedObjects]) {
if (![object validateForDelete:error]) {
return NO;
}
}
return YES;
}
// NSManagedObject 中验证对象插入的方法
- (BOOL)validateForInsert:(NSError **)error {
// 验证所有属性
for (NSAttributeDescription *attribute in [self.entity attributes]) {
id value = [self valueForKey:attribute.name];
if (![self _validateValue:&value forKey:attribute.name error:error]) {
return NO;
}
}
// 验证所有关系
for (NSRelationshipDescription *relationship in [self.entity relationships]) {
id value = [self valueForKey:relationship.name];
if (![self _validateValue:&value forKey:relationship.name error:error]) {
return NO;
}
}
// 调用子类的验证方法
if ([self respondsToSelector:@selector(validateForInsert:)]) {
return [self performSelector:@selector(validateForInsert:) withObject:error];
}
return YES;
}
Core Data 支持强大的 Undo/Redo 功能,其实现涉及与 NSUndoManager
的集成:
// NSManagedObjectContext 中 Undo/Redo 的部分实现
@interface NSManagedObjectContext () {
// 撤销管理器
NSUndoManager *_undoManager;
// 其他成员变量...
}
// 设置撤销管理器
@property (nullable, strong) NSUndoManager *undoManager;
// 注册撤销操作
- (void)_registerUndoWithTarget:(id)target selector:(SEL)selector object:(id)object;
- (void)_registerUndoForInsertedObject:(NSManagedObject *)object;
- (void)_registerUndoForDeletedObject:(NSManagedObject *)object;
- (void)_registerUndoForUpdatedObject:(NSManagedObject *)object;
@end
// 设置撤销管理器的方法
- (void)setUndoManager:(NSUndoManager *)undoManager {
if (_undoManager != undoManager) {
// 如果之前有撤销管理器,移除所有操作
if (_undoManager) {
[_undoManager removeAllActions];
}
_undoManager = undoManager;
// 如果设置了新的撤销管理器,注册初始状态
if (_undoManager) {
[self _registerInitialStateWithUndoManager:_undoManager];
}
}
}
// 注册对象插入的撤销操作
- (void)_registerUndoForInsertedObject:(NSManagedObject *)object {
if (!self.undoManager) return;
[self.undoManager registerUndoWithTarget:self selector:@selector(_undoInsertObject:) object:object];
[self.undoManager setActionName:[NSString stringWithFormat:@"Insert %@", [object.entity name]]];
}
// 撤销插入操作的方法
- (void)_undoInsertObject:(NSManagedObject *)object {
[self deleteObject:object];
[self.undoManager registerUndoWithTarget:self selector:@selector(_redoInsertObject:) object:object];
}
// 重做插入操作的方法
- (void)_redoInsertObject:(NSManagedObject *)object {
[self insertObject:object];
[self.undoManager registerUndoWithTarget:self selector:@selector(_undoInsertObject:) object:object];
}
Core Data 实现了惰性加载和预取机制,提高数据访问效率:
// NSManagedObject 中惰性加载的部分实现
@interface NSManagedObject () {
// 对象是否为故障状态
BOOL _isFault;
// 故障恢复信息
NSDictionary *_faultContext;
// 其他成员变量...
}
// 检查对象是否为故障状态
@property (readonly, getter=isFault) BOOL fault;
// 触发故障恢复
- (void)_awakeFromFetchWithRequest:(NSFetchRequest *)request context:(NSManagedObjectContext *)context;
- (void)_awakeFromInsert;
- (void)_turnIntoFault;
@end
// 检查对象是否为故障状态
- (BOOL)isFault {
return _isFault;
}
// 访问属性时触发故障恢复
- (id)valueForKey:(NSString *)key {
// 如果对象是故障状态,先触发恢复
if (self.isFault) {
[self _willAccessValueForKey:key];
}
// 调用父类实现
return [super valueForKey:key];
}
// 触发故障恢复的方法
- (void)_willAccessValueForKey:(NSString *)key {
if (self.isFault) {
// 恢复对象
[self _awakeFromFault];
}
}
// NSFetchRequest 中预取的部分实现
@interface NSFetchRequest () {
// 预取规则
NSMutableDictionary *_relationshipKeyPathsForPrefetching;
// 其他成员变量...
}
// 设置预取规则
- (void)setRelationshipKeyPathsForPrefetching:(nullable NSArray *)relationshipKeyPaths;
- (nullable NSArray *)relationshipKeyPathsForPrefetching;
@end
// 设置预取规则的方法
- (void)setRelationshipKeyPathsForPrefetching:(NSArray *)relationshipKeyPaths {
if (!relationshipKeyPaths) {
_relationshipKeyPathsForPrefetching = nil;
return;
}
_relationshipKeyPathsForPrefetching = [NSMutableDictionary dictionary];
for (NSString *keyPath in relationshipKeyPaths) {
[_relationshipKeyPathsForPrefetching setObject:@YES forKey:keyPath];
}
}
Core Data 的轻量级迁移机制允许在模型发生简单变化时自动迁移数据:
// NSPersistentStoreCoordinator 中轻量级迁移的部分实现
- (BOOL)_attemptLightweightMigrationToManagedObjectModel:(NSManagedObjectModel *)model forStoreAtURL:(NSURL *)storeURL error:(NSError **)error {
// 检查源模型和目标模型是否兼容轻量级迁移
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeURL error:error];
if (!sourceMetadata) {
return NO;
}
NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:nil forStoreMetadata:sourceMetadata];
if (![model isConfiguration:nil compatibleWithStoreMetadata:sourceMetadata]) {
if (error) {
*error = [NSError errorWithDomain:NSPersistentStoreCoordinatorErrorDomain code:NSPersistentStoreIncompatibleVersionHashError userInfo:@{NSLocalizedDescriptionKey: @"Model and store are incompatible"}];
}
return NO;
}
// 创建映射模型
NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:sourceModel destinationModel:model error:error];
if (!mappingModel) {
return NO;
}
// 执行迁移
return [mappingModel migrateStoreFromURL:storeURL
type:NSSQLiteStoreType
options:nil
withMappingModel:mappingModel
toDestinationURL:storeURL
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:error];
}
// 添加持久化存储时尝试轻量级迁移
- (NSPersistentStore *)addPersistentStoreWithType:(NSString *)storeType configuration:(NSString *)configuration URL:(NSURL *)storeURL options:(NSDictionary *)options error:(NSError **)error {
// 检查是否启用了自动迁移
BOOL shouldMigrateAutomatically = NO;
BOOL shouldInferMappingModelAutomatically = NO;
if (options) {
shouldMigrateAutomatically = [options[NSPersistentStoreMigrateAutomaticallyOption] boolValue];
shouldInferMappingModelAutomatically = [options[NSInferMappingModelAutomaticallyOption] boolValue];
}
// 如果启用了自动迁移,尝试轻量级迁移
// 如果启用了自动迁移,尝试轻量级迁移
if (shouldMigrateAutomatically && shouldInferMappingModelAutomatically) {
// 获取当前模型
NSManagedObjectModel *currentModel = self.managedObjectModel;
// 检查存储的元数据
NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:storeType URL:storeURL error:error];
if (storeMetadata) {
// 检查存储的模型版本是否与当前模型兼容
if (![currentModel isConfiguration:nil compatibleWithStoreMetadata:storeMetadata]) {
// 尝试轻量级迁移
if ([self _attemptLightweightMigrationToManagedObjectModel:currentModel forStoreAtURL:storeURL error:error]) {
// 迁移成功,继续添加存储
} else {
// 轻量级迁移失败
if (error) {
*error = [NSError errorWithDomain:NSPersistentStoreCoordinatorErrorDomain code:NSPersistentStoreIncompatibleVersionHashError userInfo:@{NSLocalizedDescriptionKey: @"Lightweight migration failed"}];
}
return nil;
}
}
}
}
// 继续常规的添加存储操作
// ...
}
轻量级迁移支持以下类型的模型变化:
Core Data 支持批量操作,允许一次性处理大量数据:
// NSBatchUpdateRequest 类的部分实现
@interface NSBatchUpdateRequest : NSPersistentStoreRequest {
// 更新的实体名称
NSString *_entityName;
// 更新的属性和值
NSDictionary *_propertiesToUpdate;
// 谓词条件
NSPredicate *_predicate;
// 返回类型
NSBatchUpdateRequestResultType _resultType;
// 其他成员变量...
}
// 初始化方法
- (instancetype)initWithEntityName:(NSString *)entityName;
// 设置更新的属性和值
@property (nonatomic, copy) NSDictionary *propertiesToUpdate;
// 设置谓词条件
@property (nonatomic, strong) NSPredicate *predicate;
// 设置返回类型
@property (nonatomic) NSBatchUpdateRequestResultType resultType;
@end
// NSBatchDeleteRequest 类的部分实现
@interface NSBatchDeleteRequest : NSPersistentStoreRequest {
// 删除的实体名称
NSString *_entityName;
// 谓词条件
NSPredicate *_predicate;
// 是否合并更改
BOOL _shouldMergeChanges;
// 其他成员变量...
}
// 初始化方法
- (instancetype)initWithEntityName:(NSString *)entityName;
// 设置谓词条件
@property (nonatomic, strong) NSPredicate *predicate;
// 设置是否合并更改
@property (nonatomic) BOOL shouldMergeChangesIntoManagedObjectContexts;
@end
批量操作的执行流程:
// NSPersistentStoreCoordinator 中执行批量操作的方法
- (id)executeRequest:(NSPersistentStoreRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)error {
if ([request isKindOfClass:[NSBatchUpdateRequest class]]) {
NSBatchUpdateRequest *updateRequest = (NSBatchUpdateRequest *)request;
// 获取对应的存储
NSPersistentStore *store = [self _storeForEntityName:updateRequest.entityName];
if (!store) {
if (error) *error = [NSError errorWithDomain:NSPersistentStoreCoordinatorErrorDomain code:NSPersistentStoreIncompatibleVersionHashError userInfo:nil];
return nil;
}
// 在存储上执行批量更新
return [store executeRequest:updateRequest withContext:context error:error];
} else if ([request isKindOfClass:[NSBatchDeleteRequest class]]) {
NSBatchDeleteRequest *deleteRequest = (NSBatchDeleteRequest *)request;
// 获取对应的存储
NSPersistentStore *store = [self _storeForEntityName:deleteRequest.entityName];
if (!store) {
if (error) *error = [NSError errorWithDomain:NSPersistentStoreCoordinatorErrorDomain code:NSPersistentStoreIncompatibleVersionHashError userInfo:nil];
return nil;
}
// 在存储上执行批量删除
return [store executeRequest:deleteRequest withContext:context error:error];
}
// 处理其他类型的请求...
return nil;
}
Core Data 查询性能优化涉及以下关键技术:
// 在数据模型中为属性添加索引
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
NSAttributeDescription *attribute = [[entity attributesByName] objectForKey:@"lastName"];
attribute.indexed = YES;
fetchLimit
和 fetchOffset
实现分页查询,避免一次加载过多数据。NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
request.fetchLimit = 20; // 每次只获取20条记录
request.fetchOffset = 40; // 从第41条记录开始获取
// 只获取对象ID,而不是完整的对象
request.resultType = NSManagedObjectIDResultType;
// 只获取特定的属性值
request.propertiesToFetch = @[@"name", @"age"];
request.resultType = NSDictionaryResultType;
relationshipKeyPathsForPrefetching
预取相关对象,减少后续查询。request.relationshipKeyPathsForPrefetching = @[@"books"]; // 预取与Person关联的books
Core Data 内存管理优化涉及以下关键技术:
// 将对象转换为故障状态,释放内存
[managedObjectContext refreshObject:object mergeChanges:NO];
NSInteger batchSize = 1000;
NSInteger offset = 0;
while (YES) {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
request.fetchLimit = batchSize;
request.fetchOffset = offset;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
if (!results || results.count == 0) {
break;
}
// 处理这批数据...
offset += batchSize;
}
NSManagedObjectContext *privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
privateContext.parentContext = mainContext;
[privateContext performBlock:^{
// 在后台处理大量数据
// ...
// 保存上下文
NSError *error = nil;
if ([privateContext save:&error]) {
// 在主上下文中合并更改
[mainContext performBlock:^{
[mainContext save:nil];
}];
}
}];
Core Data 存储优化涉及以下关键技术:
NSDictionary *options = @{
NSSQLitePragmasOption: @{@"journal_mode": @"WAL"}, // 使用 WAL 模式提高写入性能
NSSQLiteManualVacuumOption: @YES, // 允许手动执行 VACUUM 命令
};
NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error];
// 使用批量更新
NSBatchUpdateRequest *updateRequest = [[NSBatchUpdateRequest alloc] initWithEntityName:@"Person"];
updateRequest.propertiesToUpdate = @{@"age": @25};
updateRequest.predicate = [NSPredicate predicateWithFormat:@"age < 25"];
NSError *error = nil;
NSBatchUpdateResult *result = [managedObjectContext executeRequest:updateRequest error:&error];
// 执行数据库 VACUUM 命令
NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: @YES};
NSError *error = nil;
BOOL success = [coordinator migratePersistentStore:store toURL:storeURL options:options withType:NSSQLiteStoreType error:&error];
Core Data 和 Realm 是 iOS 开发中常用的两种数据持久化方案,它们的比较如下:
性能:
API 易用性:
跨平台支持:
社区与生态系统:
源码实现差异:
Core Data 与直接使用 SQLite 的比较如下:
抽象级别:
性能:
功能丰富度:
学习曲线:
Core Data 与 UserDefaults 的比较如下:
数据类型支持:
数据量:
性能:
使用场景:
Core Data 模型设计的最佳实践包括:
合理设计实体和关系:
使用轻量级迁移:
避免深嵌套关系:
为频繁查询的属性添加索引:
Core Data 代码实现的最佳实践包括:
使用 NSFetchedResultsController:
合理使用多上下文架构:
避免阻塞主线程:
performBlock
或 performBlockAndWait
在后台队列执行耗时操作。正确处理错误:
Core Data 测试与调试的最佳实践包括:
使用内存存储进行测试:
启用 SQL 日志:
编写单元测试:
使用 Instruments 进行性能分析:
随着 SwiftUI 的普及,Core Data 与 SwiftUI 的集成将更加紧密:
直接绑定:
声明式查询:
简化数据展示:
未来 Core Data 可能会在性能方面进行更多优化:
更好的内存管理:
更快的查询执行:
并行处理:
虽然 Core Data 目前是 Apple 平台特有的,但未来可能会有跨平台支持的发展:
Swift 多平台支持:
与其他数据库的集成:
未来 Core Data 可能会简化其 API,降低学习曲线:
更现代的 API:
减少样板代码:
自动代码生成:
Core Data 可能会进一步加强与 Apple 云服务的集成:
CloudKit 集成:
多设备同步:
后台同步:
陷阱:在多个线程中共享同一个 NSManagedObjectContext 实例,导致数据不一致或崩溃。
解决方案:
performBlock
和 performBlockAndWait
方法确保所有操作在上下文的队列上执行。陷阱:长时间保留大量托管对象,导致内存占用过高。
解决方案:
fetchLimit
和 fetchOffset
实现分页查询,避免一次加载过多数据。陷阱:未能正确维护实体之间的关系,导致数据不一致。
解决方案:
陷阱:模型更新后未正确处理数据迁移,导致应用崩溃或数据丢失。
解决方案:
陷阱:查询性能低下,影响应用响应速度。
解决方案:
relationshipKeyPathsForPrefetching
预取相关对象,减少后续查询。假设我们正在开发一个简单的笔记应用,使用 Core Data 存储笔记数据。
数据模型设计:
Core Data 堆栈设置:
数据操作实现:
与 UI 集成:
假设我们正在开发一个社交网络应用,使用 Core Data 存储用户数据、好友关系、消息等。
数据模型设计:
Core Data 堆栈设置:
性能优化:
并发处理:
数据迁移策略:
假设我们正在开发一个混合应用,需要将 Core Data 与其他技术集成。
与 CloudKit 集成:
与 REST API 集成:
与 SwiftUI 集成:
与第三方库集成:
Core Data 支持在查询中使用各种表达式和函数:
// 使用聚合函数
NSExpressionDescription *countExpressionDescription = [[NSExpressionDescription alloc] init];
[countExpressionDescription setName:@"count"];
[countExpressionDescription setExpression:[NSExpression expressionForFunction:@"count:" arguments:@[[NSExpression expressionForKeyPath:@"name"]]]];
[countExpressionDescription setExpressionResultType:NSInteger64AttributeType];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
[request setPropertiesToFetch:@[countExpressionDescription]];
[request setResultType:NSDictionaryResultType];
// 使用自定义表达式
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SUBSTRING(name, 0, 1) == %@", @"A"];
[request setPredicate:predicate];
在某些特殊情况下,可以使用原始 SQL 查询:
// 执行原始 SQL 查询
NSString *sql = @"SELECT * FROM Person WHERE age > 18";
NSArray *results = [managedObjectContext executeFetchRequest:request withSQL:sql error:&error];
// 执行原始 SQL 插入/更新/删除
NSString *updateSQL = @"UPDATE Person SET age = age + 1 WHERE name LIKE 'A%'";
BOOL success = [managedObjectContext executeRequest:request withSQL:updateSQL error:&error];
Core Data 允许创建自定义的持久化存储:
// 创建自定义持久化存储类
@interface MyCustomStore : NSPersistentStore
@end
@implementation MyCustomStore
// 实现必要的方法
- (BOOL)load:(NSError **)error {
// 实现存储加载逻辑
return YES;
}
- (id)executeRequest:(NSPersistentStoreRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)error {
// 实现请求执行逻辑
return nil;
}
// 其他必要的方法...
@end
// 注册自定义存储类型
[NSClassFromString(@"NSPersistentStoreCoordinator") registerStoreClass:[MyCustomStore class] forStoreType:@"MyCustomStoreType"];
Core Data 提供了多种扩展点,可以自定义其行为:
// 自定义 NSManagedObject 子类
@interface Person : NSManagedObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSNumber *age;
// 自定义方法
- (void)incrementAge;
@end
@implementation Person
- (void)incrementAge {
self.age = @([self.age integerValue] + 1);
}
// 验证方法
- (BOOL)validateName:(id *)ioValue error:(NSError **)outError {
NSString *name = *ioValue;
if (name.length == 0) {
if (outError) {
*outError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSValidationMissingMandatoryPropertyError userInfo:@{NSLocalizedDescriptionKey: @"Name cannot be empty"}];
}
return NO;
}
return YES;
}
@end
// 自定义 NSManagedObjectContext 子类
@interface MyManagedObjectContext : NSManagedObjectContext
// 自定义保存方法
- (BOOL)saveWithValidation:(NSError **)error;
@end
@implementation MyManagedObjectContext
- (BOOL)saveWithValidation:(NSError **)error {
// 执行额外的验证
if (![self _validateAllObjects:error]) {
return NO;
}
// 调用父类方法
return [super save:error];
}
@end
在后台任务中使用 Core Data 需要特别注意:
// 在后台任务中使用 Core Data
__block UIBackgroundTaskIdentifier backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
// 任务超时处理
[application endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}];
// 创建私有队列上下文
NSManagedObjectContext *privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
privateContext.parentContext = mainContext;
[privateContext performBlock:^{
// 在后台执行数据操作
// ...
// 保存上下文
NSError *error = nil;
if ([privateContext save:&error]) {
// 在主上下文中合并更改
[mainContext performBlock:^{
[mainContext save:nil];
// 结束后台任务
[application endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}];
} else {
// 处理错误
[application endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}
}];
错误描述:数据库被锁定,无法执行操作。
可能原因:
解决方案:
错误描述:持久化存储的模型版本与当前应用的模型不匹配。
可能原因:
解决方案:
错误描述:对象验证失败,无法保存。
可能原因:
解决方案:
错误描述:应用因内存不足被系统终止。
可能原因:
解决方案:
refreshObject:mergeChanges:
将对象转换为故障状态。错误描述:在错误的线程上访问上下文或对象。
可能原因:
解决方案:
performBlock
和 performBlockAndWait
。NSFetchedResultsController 是一个专门为 UITableView 和 UICollectionView 设计的控制器,它可以自动跟踪 Core Data 数据的变化并更新视图:
// 设置 NSFetchedResultsController
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
fetchRequest.sortDescriptors = @[sortDescriptor];
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
controller.delegate = self;
// 实现 NSFetchedResultsControllerDelegate 方法
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
Core Data 可以与 CloudKit 集成,实现数据的云端同步:
// 设置 CloudKit 容器
CKContainer *container = [CKContainer defaultContainer];
CKDatabase *database = [container privateCloudDatabase];
// 创建导出操作
NSBatchExportRequest *exportRequest = [[NSBatchExportRequest alloc] initWithEntityName:@"Person"];
exportRequest.predicate = [NSPredicate predicateWithFormat:@"needsSync == YES"];
// 执行导出操作
[managedObjectContext executeRequest:exportRequest completionHandler:^(NSBatchExportResult * _Nullable result, NSError * _Nullable error) {
if (error) {
// 处理错误
return;
}
// 获取导出的数据
NSArray *metadataObjects = result.metadataObjects;
// 上传到 CloudKit
for (NSCKExportMetadata *metadata in metadataObjects) {
CKRecord *record = [self recordFromMetadata:metadata];
[database saveRecord:record completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
if (!error) {
// 更新本地对象的同步状态
[self markObjectAsSynced:metadata.objectID];
}
}];
}
}];
// 创建导入操作
NSBatchImportRequest *importRequest = [[NSBatchImportRequest alloc] initWithEntityName:@"Person"];
importRequest.predicate = [NSPredicate predicateWithFormat:@"modified > %@", lastSyncDate];
// 执行导入操作
[managedObjectContext executeRequest:importRequest completionHandler:^(NSBatchImportResult * _Nullable result, NSError * _Nullable error) {
if (error) {
// 处理错误
return;
}
// 合并导入的数据
[self mergeImportedData:result.importedObjects];
}];