提問與回答
蘋果系統生成的模板中已經把 Core Data 的基礎準備都放在 AppDelegate 中了,為什么還要自己封裝?
- 因為:基礎準備代碼比較繁瑣,不容易記憶, 基礎準備一經設置,也無法修改,為了提高靈活運用,還是自己封裝一下比較好!
基礎知識了解
-
Core Data 的核心對象都不是線程安全的,封裝此框架之前,需要先了解一下的類:
- NSManagedObjectContext 管理對象上下文
- NSManagedObjectModel 管理對象模型
- NSPersistentStoreCoordinator 持久化存儲調度器
-
思維導圖,蘋果官方給出的coreData的存儲示意圖如下:
操作步驟
新建 coreData工具類
建立單例對象
- 單例的實現
<pre>
+(instancetype)shareManager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
// 重寫init方法
(instancetype)init
{
self = [super init];
if (self) {
[self managedObjectContext];
}
return self;
}
</pre>-
單例方法中什么時候需要實現 allocWithZone: 方法?
- 如果單例對象提供的方法,允許用戶進行私人定制,則無需實現 allocWithZone:,例如:NSURLSession
- 如果單例對象中提供的操作涉及到線程安全,并且確定沒有定制需求,則應該實現 allocWithZone: 方法
Core Data Stack 相關方法
- 新建 Model.xcdatamodeld,注意文件名可以隨便寫,并且建立 Person 實體
- 從 AppDelegate 復制 managedObjectContext
// 創建一個只讀上下文本屬性
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
- 利用 @synthesize 指定成員變量
@synthesize managedObjectContext = _managedObjectContext;
- 將 persistentStoreCoordinator 和 managedObjectModel 中的關鍵代碼順序復制到 managedObjectContext 的 getter 方法中
- (NSManagedObjectContext *)managedObjectContext {
// 返回已經綁定到`持久化存儲調度器`的管理對象上下文
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
// 數據模型的 URL
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];
// 從 Bundle 加載對象模型
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
// 創建持久化存儲調度器
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
// 指定保存在磁盤的數據庫文件 URL
NSURL *applicationURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [applicationURL URLByAppendingPathComponent:dbName];
if ([psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:NULL] == nil) {
NSLog(@"創建數據庫錯誤");
return nil;
}
// 創建管理對象上下文,并且指定并發類型
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
// 設置管理上下文的存儲調度器
[_managedObjectContext setPersistentStoreCoordinator:psc];
return _managedObjectContext;
}
思維導圖如下:
- 復制并修改 saveContext 方法
- (BOOL)saveContext{
// 判斷上下文是否為 nil
if (self.managedObjectContext == nil) {
NSLog(@"上下文為nil,無法進行數據操作");
return NO;
}
NSError *error = nil;
if (self.managedObjectContext.hasChanges && ![self.managedObjectContext save:&error]) {
NSLog(@"沒有需要保存的數據");
return NO;
}
[self.backgroundMoc save:NULL];
return YES;
}
框架已上傳到github: https://github.com/CandyGentleman/coreData.git如有不足之處,歡迎指出!