Инициализация основных данных
Просматривая документацию Apple, я вижу, что они рекомендуют удалить код инициализации Core Data из AppDelegate. Их подход ниже.
Что я не понимаю, так это следующее
- Предложение ниже в документации. Как происходит обратный вызов делегата приложения? Я не вижу ни одного в фрагментах кода ниже. Это то, что они хотят, чтобы мы добавили.
Инициализируя отдельный объект контроллера с блоком завершения, вы удалили стек основных данных из делегата приложения, но по- прежнему разрешаете обратный вызов делегату приложения, чтобы пользовательский интерфейс мог знать, когда начинать запрашивать данные.
- AppDelegate вызывает init DataController, а это, в свою очередь, вызывает 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]);
});
}
2 ответа
1)
В руководстве по программированию Core Data, на которое вы смотрите, авторы извлекают Core Data из App Delegate (который имеет тенденцию быть загроможденным большим количеством дополнительного кода, который разработчики действительно должны разделить на отдельные объекты).
Остальная часть документации объясняет:
Рекомендуется, чтобы базовый стек данных создавался в его собственном объекте контроллера верхнего уровня, и чтобы делегат приложения инициализировал этот объект контроллера и содержал ссылку на него. Это действие будет способствовать консолидации кода Core Data в его собственном контроллере и сохранит делегат приложения относительно чистым.
Также:
назначить добавление постоянного хранилища (
NSPersistentStore
) постоянному координатору магазина (NSPersistentStoreCoordinator
) в фоновую очередь. Это действие может занять неизвестное количество времени, а выполнение его в основной очереди может заблокировать пользовательский интерфейс, что может привести к завершению работы приложения.Как только постоянное хранилище добавлено в координатор постоянного хранилища, вы можете затем перезвонить в основную очередь и запросить завершение пользовательского интерфейса и отображение его пользователю.
Так что да, CoreData может не обязательно быть полностью активным к тому времени, когда отображается ваш первый контроллер представления, но если у вас есть наблюдатель, ищущий NSNotification
из этой фоновой очереди вы можете сообщить своему пользовательскому интерфейсу, когда CoreData готова к использованию.
2)
[DataController init]
не вернет DataController
возражать до initializeCoreData
возвращается, поэтому ваш интерфейс не будет отображаться до didFinishLaunchingWithOptions
возвращается, и вы уже должны иметь DataController
объект.
Возврат YES
из метода applicationDidFinishLaunchingWithOptions
это ключ.
Инициализация стека базовых данных происходит до возврата метода или, скорее, до инициализации любого контроллера представления. Стек данных ядра инициализируется, как только приложение уведомляется о том, что оно действительно запускается. Только после всего процесса инициализации, метод возвращает YES
, После чего раскадровка загружается вместе со своим начальным контроллером, а затем начальным контроллером viewDidLoad
загружается.
Таким образом, задолго до того, как начальный контроллер окажется на экране, загружается стек данных Core.
Надеюсь, это поможет вам понять.