看一下苹果的文档,我发现他们建议将核心数据初始化代码从AppDelegate中删除。他们的做法如下。
我不明白的是以下几点
通过使用完成块初始化单独的控制器对象,您已经将核心数据堆栈从应用程序委托中移出,但是您的仍然允许对应用程序委托进行回调,以便用户界面能够知道何时开始请求数据。
文档中的AppDelegate代码
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self setDataController:[[DataController alloc] init];
// Basic User Interface initialization
return YES;
}文档中的DataController代码
@interface MyDataController : NSObject
@property (strong) NSManagedObjectContext *managedObjectContext;
-(void)initializeCoreData;
@end
@implementation MyDataController
-(id)init {
self = [super init];
if (!self) return nil;
[self initializeCoreData];
return self;
}
- (void)initializeCoreData {
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DataModel" withExtension:@"momd"];
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSAssert(mom != nil, @"Error initializing Managed Object Model");
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[moc setPersistentStoreCoordinator:psc];
[self setManagedObjectContext:moc];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentsURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [documentsURL URLByAppendingPathComponent:@"DataModel.sqlite"];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSError *error = nil;
NSPersistentStoreCoordinator *psc = [[self managedObjectContext] persistentStoreCoordinator];
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];
NSAssert(store != nil, @"Error initializing PSC: %@\n%@", [error localizedDescription], [error userInfo]);
});
}发布于 2016-09-18 16:59:54
1)
在核心数据编程指南中,您将看到,作者正在将核心数据从App中提取出来(它往往会被大量额外的代码弄得乱七八糟,开发人员确实应该将这些代码分割成单独的对象)。
文件的其余部分解释:
建议在它自己的顶级控制器对象中创建Core数据堆栈,并且应用程序委托初始化该控制器对象并保存对它的引用。此操作将促进核心数据代码在其自己的控制器中的合并,并保持应用程序委托相对干净。
另外:
将持久化存储(
NSPersistentStore)添加到持久存储协调器(NSPersistentStoreCoordinator)到后台队列。该操作可能会花费未知的时间,在主队列上执行该操作会阻塞用户界面,可能导致应用程序终止。 一旦将持久存储添加到持久存储协调器中,您就可以调用主队列并请求完成用户界面并将其显示给用户。
因此,在显示第一个视图控制器时,CoreData可能不一定完全打开,但是如果您有一个观察者从该后台队列中查找NSNotification,则可以告诉您的UI何时可以依赖CoreData。
2)
[DataController init]在[DataController init]返回之前不会返回DataController对象,因此您的UI直到didFinishLaunchingWithOptions返回之后才会显示,并且您应该已经有了一个DataController对象。
发布于 2016-09-18 17:00:15
从方法YES返回applicationDidFinishLaunchingWithOptions是关键。
核心数据堆栈的初始化发生在方法返回之前,或者更确切地说是在初始化任何视图控制器之前。一旦通知应用程序它确实正在启动,核心数据栈就会被初始化。只有在整个初始化过程之后,该方法才返回YES。之后,故事板与其初始控制器一起加载,然后加载初始控制器的viewDidLoad。
所以在某种程度上,在初始控制器甚至出现在屏幕上之前的很长一段时间内,核心数据堆栈都会被加载。
希望这能帮你理解。
https://stackoverflow.com/questions/39560195
复制相似问题