iOS 10 以前創建CoreDataStack
1 Data Model
Data Model 是Xcode提供的一個可視化Model 編輯器,可以創建實例,定義實例屬性,定義實例之間的關系,以及創建一些常用的FetchRequst
1.1 新建DataModel 文件
1.2 添加實例&定義屬性
1.21 屬性類型(Attribute Type)
- Integer16 Integer32 Integer64
- Decimal Float Double
- String
- Boolean
- Date
- Binary Data
- Transformable
其中,Binary Data
為二進制數據,在Xcode右側Model Inspector 中,有一個可以設置Allows External Storage
的選項,CoreData會智能選擇是存儲文件的二進制數據,還是存儲文件URL
Transformable
可以為任意遵循NSCoding
協議的對象類型
1.3 添加關系(relationShip)
- to one (一對一)
- to Manay (一對多)
這里再定義一個實例,主人(master),設定主人和狗子的關系為一對多,關系圖如下:
2 CoreDataStack
CoreDataStck,是自定義的一個CoreData 的棧對象,為一個單例,可以通過它,初始化項目的CoreData,以及獲取到Context,對數據庫進行增刪改查等操作
2.1 單例
// CoreDataStack.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface CoreDataStack : NSObject
+ (instancetype)sharedInstance;
@end
// CoreDataStack.m
#import "CoreDataStack.h"
@implementation CoreDataStack
+ (instancetype)sharedInstance {
static CoreDataStack *stack;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
stack = [[CoreDataStack alloc] init];
});
return stack;
}
@end
3 NSManagedModel
The NSManagedObjectModel represents each object type in your app's data model, the properties they can have, and the relationship between them.
// CoreDataStack.m
@interface CoreDataStack ()
@property (nonatomic, strong) NSManagedObjectModel *managedModel;
@end
......
- (NSManagedObjectModel *)managedModel {
if (!_managedModel) {
NSURL *momdURL = [[NSBundle mainBundle]URLForResource:@"Model" withExtension:@"momd"];
_managedModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momdURL];
}
return _managedModel;
}
NSManagedObjectModel
通過Xcode創建的DataModel
文件初始化,DataModel文件編譯后的后綴為momd
。
4 NSPersistentStoreCoordinator
4.1 NSpersistentStore
atomic vs nonatomic
An atomic persistent store needs to be completely deserialized and loaded into memory before you can make any read or write operations. In contrast, a non- atomic persistent store can load chunks of itself onto memory as needed.
type
- NSSQLiteStoreType (nonatomic)
- NSXMLStoreType (atomic)
- NSBinaryStoreType (atomic)
- NSInMemoryStoreType (atomic)
4.2 NSPersistentStoreCoordinator
the bridge between the managed object model and the persistent store
- 通過
managed object model
初始化 - 通過
addPersistentStoreWithType:configuration:URL:options:error:
添加persistent store
// CoreDataStack.m
@interface CoreDataStack ()
@property (nonatomic, strong) NSPersistentStoreCoordinator *psc;
@end
......
- (NSPersistentStoreCoordinator *)psc {
if (!_psc) {
_psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedModel];
NSURL *URL = [[self documentURL] URLByAppendingPathComponent:@"Model.sqlite"];
NSError *error;
if (![_psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:URL options:nil error:&error]) {
NSLog(@"addPersistentStoreWithType Error: %@",[error localizedDescription]);
}
}
return _psc;
}
- (NSURL *)documentURL {
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
}
5 NSManagedObjectContext
Context是唯一暴露給外界,供外界使用的接口
- context an in-memory scratchpad for managed objects.
- any change you make won't affect the underlying data on disk until you call
-save:
of context- context manages the lifecycle of the objects that it creates or fetches.
- A managed object cannot exist without an associated context.
- once a managed object has associated with a particular context, it will remain associated with the same context for the duration of its lifecycle.
- context and managed object is not thread safe
// CoreDataStack.h
@interface CoreDataStack : NSObject
@property (nonatomic, strong, readonly) NSManagedObjectContext *managedContext;
@end
// CoreDataStack.m
@interface CoreDataStack ()
@property (nonatomic, strong, readwrite) NSManagedObjectContext *managedContext;
@end
- (NSManagedObjectContext *)managedContext {
if (!_managedContext) {
_managedContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedContext.persistentStoreCoordinator = self.psc;
}
return _managedContext;
}
6 Save Context
- (void)saveContext {
NSError *error;
if ([self.managedContext hasChanges] && ![self.managedContext save:&error]) {
NSLog(@"NSManagedObjectContext Save Error: %@",[error localizedDescription]);
}
}
iOS 10 以后創建CoreDataStack
iOS 10 以后,蘋果系統為我們封裝了一個CoreData Stack 的類,叫NSPersistentContainer
,可以通過它的屬性viewContext
獲取到NSManagedObjectContext
@property (readonly, strong) NSPersistentContainer *persistentContainer;
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"testCoreData"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
- (void)saveContext {
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}
源碼下載
https://github.com/mengtian-li/CoreDataStackDemo/releases/tag/v0.1