2

查看 Apple 文档,我看到他们建议从 AppDelegate 中删除 Core Data 初始化代码。他们的方法如下。

我不明白的是以下

  1. 文档中的以下句子。应用程序委托如何回调?我在下面的代码片段中没有看到。这是他们想要我们添加的东西吗?

通过使用完成块初始化一个单独的控制器对象,您已经将 Core Data 堆栈从应用程序委托中移出,但您仍然允许对应用程序委托进行回调,以便用户界面可以知道何时开始请求数据。

  1. AppDelegate 调用 DataController 的 init,而这又调用了 initializeCoreData。但是 initializeCoreData 在后台线程中设置持久存储协调器。这意味着如果我们转换到应用程序的第一个视图并且它的视图控制器从核心数据请求数据,事情还没有建立起来。这不会是个问题吗?这是否意味着他们希望我们显示不同的启动屏幕并注册一个回调,告诉我们 CoreData 初始化在移动到实际的第一个应用程序视图之前完成。

文档中的 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]);
    });
}
4

2 回答 2

1

1)

在您正在查看的 Core Data 编程指南中,作者正在将 Core Data 从 App Delegate 中取出(这往往会被开发人员真正应该拆分成单独对象的大量额外代码弄得一团糟)。

文档的其余部分解释:

建议在其自己的顶级控制器对象中创建核心数据堆栈,并且应用程序委托初始化该控制器对象并持有对它的引用。此操作将促进核心数据代码在其自己的控制器中的整合,并保持应用程序委托相对干净。

还:

将持久存储 ( NSPersistentStore) 的添加分配给持久存储协调器 ( NSPersistentStoreCoordinator) 到后台队列。该操作可能需要未知量的时间,并且在主队列上执行它可能会阻塞用户界面,可能导致应用程序终止。

将持久存储添加到持久存储协调器后,您可以回调主队列并请求完成用户界面并将其显示给用户

所以是的,当你的第一个视图控制器显示时,CoreData 可能不一定完全启动,但是如果你有一个观察者NSNotification从那个后台队列中寻找一个,你可以告诉你的 UI 什么时候可以依赖 CoreData。

2)

[DataController init]在返回之前不会返回DataController对象initializeCoreData,因此您的 UI 在返回之后才会显示,didFinishLaunchingWithOptions并且您应该已经有一个DataController对象。

于 2016-09-18T16:59:54.497 回答
0

YES方法的返回applicationDidFinishLaunchingWithOptions,是关键。

Core Data 堆栈的初始化发生在方法返回之前,或者更确切地说是在任何视图控制器被初始化之前。一旦通知应用程序确实正在启动,就会初始化核心数据堆栈。只有在整个初始化过程之后,该方法才返回YES. 之后故事板连同它的初始控制器一起被加载,然后初始控制器viewDidLoad被加载。

所以在某种程度上,甚至在初始控制器出现在屏幕上之前很长一段时间,Core 数据堆栈都已加载。

希望这可以帮助您理解。

于 2016-09-18T17:00:15.460 回答