2016-09-18 13 views
1

В документации Apple я вижу, что они рекомендуют удалить код инициализации Core Data из AppDelegate. Их подход ниже.Инициализация основных данных

То, что я не понимаю, являются следующие

  1. Предложение ниже в документации. Как происходит обратный вызов делегата приложения? Я не вижу этого в фрагментах кода ниже. Это то, что они хотят, чтобы мы добавили.

При инициализации отдельного объекта контроллера с блоком завершения, вы переместились стек основные данные из делегата приложения, но вы все еще допускаете обратный вызов для приложения делегата так, что пользовательский интерфейс может знать когда начинать запрашивать данные.

  1. AppDelegate вызывает init DataController, и это, в свою очередь, вызывает инициализациюCoreData. Но 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]); 
    }); 
} 

ответ

1

1)

In the Core Data programming guide you're looking at, авторы принимают Core Data из App вычеркивать знак gate (который, как правило, забивается большим количеством дополнительного кода, который разработчики должны разделить на отдельные объекты).

Остальная часть документации объясняет:

Рекомендуется, чтобы стек основные данные будут создана в рамках своего верхнего уровня объекта контроллера и что приложение делегат инициализировать этот объект контроллера и удерживайте ссылку к нему. Это действие будет способствовать консолидации кода основных данных в его собственном контроллере и будет оставаться делегатом относительно прозрачным.

Также:

назначить добавление постоянной памяти (NSPersistentStore) к координатору постоянного хранилища (NSPersistentStoreCoordinator) на фоне очереди в. Это действие может занять неизвестное время, а , выполняющее его в основной очереди, может заблокировать пользовательский интерфейс, возможно , заставляя приложение прекратить работу.

После того, как настойчивый магазин был добавлен к постоянному координатору магазина , вы можете перезвонить в главной очереди и запросить , что пользовательский интерфейс будет завершен и отображается пользователю

Так что да, К тому времени, когда отображается ваш первый контроллер представлений, CoreData может не полностью соответствовать, но если у вас есть наблюдатель, ищущий NSNotification из этой фоновой очереди, вы можете указать свой интерфейс, когда CoreData готов к использованию.

2)

[DataController init] не будет возвращать DataController объект до initializeCoreData возвращается, так что ваш интерфейс не будет отображаться до тех пор, после того, как didFinishLaunchingWithOptions возвращается, и вы уже должны иметь DataController объект.

+0

Я не согласен. У 'initializeCoreData' есть' dispatch_async' в конце. Таким образом, он будет возвращен до выполнения этого блока кода. Следовательно, нет гарантии, что блок внутри 'disaptch_async'' initializeCoreData' завершился, когда [DataController init] вернулся. –

+0

Вы правы. Вам нужно будет сообщить своему пользовательскому интерфейсу, что CoreData готов к использованию. Один из способов сделать это - через NSNotifications, или другой способ - иметь «свойство» (например, Bool?), Которое получает значение true, чтобы наблюдатель ключевых значений мог срабатывать, когда пользовательский интерфейс может полагаться на CoreData. –

+0

@SmartHome - обсуждение [iCloud-core-data] (https://developer.apple.com/library/content/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/UsingSQLiteStoragewithiCloud/UsingSQLiteStoragewithiCloud.html#//apple_ref/doc/uid/ TP40013491-CH3-SW1) рассказывает об уведомлениях, которые даются, когда хранилище temp заменяется «реальным» хранилищем. Я подозреваю, что они предлагают код, который упрощает переход приложения с локальным хранилищем в хранилище облаков. Но, как ни странно, они не показывают * как * обрабатывать PSCDidChange и как повторно отображать пользовательский интерфейс. Документ iCloud предлагает вам просто «перезагрузить» MOC. – stevesliva

0

Возврат YES по методу applicationDidFinishLaunchingWithOptions, является ключом.

Инициализация стека основных данных происходит до возврата метода или, скорее, до того, как будет инициализирован любой контроллер представления. Базовый блок данных инициализируется, как только приложение будет уведомлено о его запуске. Его только после всего процесса инициализации, метод возвращает YES. После чего загружается раскадровка вместе с ее начальным контроллером, а затем загружается начальный контроллер viewDidLoad.

Таким образом, до того, как начальный контроллер находится на экране даже на экране, загружается стек данных Core.

Надеюсь, это поможет вам разобраться.

+1

Я не согласен. У 'initializeCoreData' есть' dispatch_async' в конце. Таким образом, он будет возвращен до выполнения этого блока кода. Следовательно, нет гарантии, что блок внутри 'disaptch_async'' initializeCoreData' был завершен, когда [DataController init] вернулся, и, следовательно, нет гарантии, что этот блок был выполнен, когда 'applicationDidFinishLaunchingWithOptions' вернул YES. –