如何在 Objective-C 的扩展代码中重用核心数据? ManagedObjectContext 不能像我们过去那样由 UIApplicationDelegate 创建
How to re-use Core Data in Extension code in Objective-C? The managedObjectContext can't be created by UIApplicationDelegate as we use to do
我遇到的问题是我们无法通过这种方式获取managedObjectContext:
[((MDAppDelegate*)appController) mainQueueContext] ;
因为报错信息是:
'sharedApplication' is unavailable: not available on iOS (App
Extension) - Use view controller based solutions where appropriate
instead.
我的问题是:
有没有现有的例子可以帮助我们通过扩展连接到核心数据(Today/Watch)?
P.S。我已阅读以下问题,其中 none 有帮助。我只需要一个例子:
App and Extension - Use Core data == error : sharedApplication()' is unavailable
WatchKit : 'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based solutions where appropriate instead
Use AppDelegate in today extension
我们现在发现并解决了问题。问题是我对Core Data的误解造成的。我们曾经重复使用教程的源代码。当系统工作时,我们没有时间深入了解它。
问题是我们无法使用容器应用程序的托管对象上下文。要修复它,我们使用以下代码:
替换
[((MDAppDelegate*)appController) mainQueueContext] ;
到
[self mainQueueContext] ;
然后,添加以下...
- (NSManagedObjectContext *)mainQueueContext {
if (_mainQueueContext != nil) {
return _mainQueueContext;
}
_mainQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainQueueContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
[_mainQueueContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
return _mainQueueContext; }
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL;
NSString *containerPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.<your project group ID>"].path;
NSString *sqlitePath = [NSString stringWithFormat:@"file://%@/%@", containerPath, @"<Your database file>.sqlite"];
storeURL = [NSURL URLWithString:sqlitePath];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
abort();
}
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storeURL.path error:&error]) {
// Handle error
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL;
NSString *containerPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.<your project group ID>"].path;
NSString *modelPath = [NSString stringWithFormat:@"file://%@/%@", containerPath, @"<Your database file>.momd"];
modelURL = [NSURL URLWithString:modelPath];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
另一个重要问题是容器应用程序仍在使用位于应用程序文档目录中的核心数据存储。扩展程序无法访问它。因此,我们使用以下行将商店迁移到组共享文件夹:
NSString *directoryShared = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.<your project group ID>"].path;
NSString *storePathShared = [NSString stringWithFormat:@"file://%@/%@", directoryShared, @"<Your database file>.sqlite"];
NSURL *storeUrlShared = [NSURL URLWithString:storePathShared];
[_persistentStoreCoordinator migratePersistentStore:store
toURL:storeUrlShared
options:options
withType:NSSQLiteStoreType
error:&error];
if (error != nil) {
NSLog(@"Error when migration to groupd url %@, %@", error, [error userInfo]);
}
我们只是保留原始数据库,让容器应用继续使用它。有一些更好的方法来实现它。像:
Migrating NSPersistentStore from application sandbox to shared group container
我遇到的问题是我们无法通过这种方式获取managedObjectContext:
[((MDAppDelegate*)appController) mainQueueContext] ;
因为报错信息是:
'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based solutions where appropriate instead.
我的问题是:
有没有现有的例子可以帮助我们通过扩展连接到核心数据(Today/Watch)?
P.S。我已阅读以下问题,其中 none 有帮助。我只需要一个例子:
App and Extension - Use Core data == error : sharedApplication()' is unavailable
WatchKit : 'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based solutions where appropriate instead
Use AppDelegate in today extension
我们现在发现并解决了问题。问题是我对Core Data的误解造成的。我们曾经重复使用教程的源代码。当系统工作时,我们没有时间深入了解它。
问题是我们无法使用容器应用程序的托管对象上下文。要修复它,我们使用以下代码: 替换
[((MDAppDelegate*)appController) mainQueueContext] ;
到
[self mainQueueContext] ;
然后,添加以下...
- (NSManagedObjectContext *)mainQueueContext {
if (_mainQueueContext != nil) {
return _mainQueueContext;
}
_mainQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainQueueContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
[_mainQueueContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
return _mainQueueContext; }
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL;
NSString *containerPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.<your project group ID>"].path;
NSString *sqlitePath = [NSString stringWithFormat:@"file://%@/%@", containerPath, @"<Your database file>.sqlite"];
storeURL = [NSURL URLWithString:sqlitePath];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
abort();
}
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storeURL.path error:&error]) {
// Handle error
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL;
NSString *containerPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.<your project group ID>"].path;
NSString *modelPath = [NSString stringWithFormat:@"file://%@/%@", containerPath, @"<Your database file>.momd"];
modelURL = [NSURL URLWithString:modelPath];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
另一个重要问题是容器应用程序仍在使用位于应用程序文档目录中的核心数据存储。扩展程序无法访问它。因此,我们使用以下行将商店迁移到组共享文件夹:
NSString *directoryShared = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.<your project group ID>"].path;
NSString *storePathShared = [NSString stringWithFormat:@"file://%@/%@", directoryShared, @"<Your database file>.sqlite"];
NSURL *storeUrlShared = [NSURL URLWithString:storePathShared];
[_persistentStoreCoordinator migratePersistentStore:store
toURL:storeUrlShared
options:options
withType:NSSQLiteStoreType
error:&error];
if (error != nil) {
NSLog(@"Error when migration to groupd url %@, %@", error, [error userInfo]);
}
我们只是保留原始数据库,让容器应用继续使用它。有一些更好的方法来实现它。像: Migrating NSPersistentStore from application sandbox to shared group container