我正在学习开发iOS应用程序的教程。我正在使用核心数据。该应用的第一个视图是RootViewController
。所有Core Data堆栈都在AppDelegate
文件上。这是来自AppDelegate.m
的代码的一部分,用于调用RootViewController
文件:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Fetch the data to see if we ought to pre-populate
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
[self loadFavoriteThingsData];
RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
[rootViewController setManagedObjectContext:[self managedObjectContext]];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
return YES;
}
现在,在应用的另一部分,我需要打开一个新视图控制器,它与RootViewController
重复,称为DoneViewController
,但使用其他NSPredicate
来显示其他核心数据对象。
在RootViewController
中有一个按钮可以打开MenuViewController
文件,我尝试使用以下方法打开DoneViewController
:
- (IBAction)doneToDoaction:(id)sender {
DoneViewController *viewController = [[DoneViewController alloc] init];
[self presentViewController:viewController animated:YES completion:nil];
}
但是引发了一个例外:
[MenuViewController managedObjectContext]: unrecognized selector sent to instance 0x145a0c00
2013-12-26 22:58:23.688 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MenuViewController managedObjectContext]: unrecognized selector sent to instance
我想我必须将managedObjectContext
从RootViewController
传递到MenuViewController
,然后从MenuViewController
传递到DoneViewController
,但我不知道如何做到这一点。
答案 0 :(得分:8)
这是因为您没有使用NSObject类。为此,你必须在AppDelegate.h中实现NSObject。就像这个..
@interface AppDelegate : UIResponder <UIApplicationDelegate,NSObject>{
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
}
并添加属性。
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (NSString *)applicationDocumentsDirectory;
还在AppDelegate.m文件中添加代码......
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil] ;
return managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
stringByAppendingPathComponent: @"<Project Name>.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error])
{
/*Error for store creation should be handled in here*/
}
return persistentStoreCoordinator;
}
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
这对我100%有效。希望这对你有用。
答案 1 :(得分:0)
很少有解决方案可以做你想做的事。
第一种是从@Gyanendra评论的应用程序委托中公开上下文。第二种是将上下文从控制器传递给控制器。如需进一步参考,我建议您阅读Marcus Zarra撰写的PASSING AROUND A NSMANAGEDOBJECTCONTEXT ON IOS。
无论如何,我更喜欢第二种解决方案。绕过上下文或抓取NSManagedObject
的实例。基于后者,每个NSManagedObjectInstance
都有对已注册的上下文的引用。
[managedObjectInstance managedObjectContext];
这些解决方案可防止严格的应用程序,并避免污染应用程序委托。
在您的情况下,您可以采用这种方法。从RootViewController
开始将上下文传递给MenuViewController
,然后从后者传递给DoneViewController
。怎么样?
足够简单。只需公开您感兴趣的控制器等属性(在这种情况下为MenuViewController
和DoneViewController
)。
@property (nonatomic, strong) NSManagedObjectContext* mainContext;
可以设置为
// from RootViewController
menuViewController.mainContext = [self managedObjectContext];