iOS - 从本地通知启动时托管对象上下文崩溃应用程序

Posted

技术标签:

【中文标题】iOS - 从本地通知启动时托管对象上下文崩溃应用程序【英文标题】:iOS - Managed object context crashes app when launching from local notification 【发布时间】:2012-12-02 11:54:49 【问题描述】:

我有一个创建本地通知的应用程序。当应用程序关闭(即未运行或在后台)时,它会在从通知启动时崩溃。我已经设法弄清楚哪一行导致应用程序崩溃(在下面的评论中说明):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];

// Initialise the main view
self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];

// Initialise a Navigation Controller
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.viewController];

// Set the ViewController as the rootViewController of the window
self.window.rootViewController = nav;

// Colour the navigation bar
nav.navigationBar.tintColor = [UIColor colorWithRed:0.07f green:0.59f blue:0.94f alpha:1];

// Set the background
if (isPhone568) 
    self.window.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"santa_back5.png"]];

else 
    self.window.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"santa_back.png"]];


[self.window makeKeyAndVisible];
[nav release];

self.viewController.managedObjectContext = [self managedObjectContext];

application.applicationIconBadgeNumber = 0;

// Handle launching from a notification
UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotif) 
    NSPredicate *predicate = [NSPredicate
                              predicateWithFormat:@"(dateCreated like %@)",
                              [localNotif.userInfo objectForKey:@"dateCreated"]];

    LetterViewController *letterView = [[LetterViewController alloc] initWithNibName:@"LetterViewController" bundle:nil];

    // Get the letter to pass on
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"Letter" inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:entity];
    [fetchRequest setPredicate:predicate];
    NSError *error;
//
// THIS NEXT LINE IS CRASHING THE APP
//
    NSArray *letters = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    Letter *myLetter = [letters objectAtIndex:0];

    letterView.theLetter = myLetter;
    //[myLetter release];

    // Pass the selected object to the new view controller.
    [self.viewController.navigationController pushViewController:letterView animated:YES];
    [letterView release];
    [fetchRequest release];


return YES;

我正在使用以下 3 个函数来获取托管对象上下文、持久存储协调器和托管对象模型:

//Explicitly write Core Data accessors
- (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] retain];

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];

对于解决此问题的任何帮助将不胜感激。

提前致谢。

【问题讨论】:

您是否收到任何错误日志? 【参考方案1】:

几件事。您似乎在显示的主线程上使用 Core Data,如果是这样,所有交互都必须在此线程上。您应该在某天更新代码以使用使用块的新“执行”API。

由于您的 localNotif 代码现在在启动委托中执行了一些繁重的工作,因此它在一段时间内不会返回,ios 可能会终止您的应用程序。采用相同的代码并将其放入发布到主队列的调度块中,它应该可以工作。添加一些断言以确保导航控制器属性也存在。

【讨论】:

感谢您提供此信息!我不知道这一点,会调查它!【参考方案2】:

感谢您的回答。似乎我的问题出在谓词上!它不喜欢我在 where 子句中使用“like”。我把它改成了一个 = 就可以了!

【讨论】:

以上是关于iOS - 从本地通知启动时托管对象上下文崩溃应用程序的主要内容,如果未能解决你的问题,请参考以下文章

iOS 本地通知 - 在后台时回调

我的 Apple Watch 从未收到托管 iOS 应用程序发送的本地通知

在 Mobilefirst V7.1 上使用 Clevertap 推送通知在启动画面上出现 iOS 应用程序崩溃问题

由于核心数据故障,应用程序在启动时崩溃

托管对象上下文作为单例?

IOS,应用启动时如何处理多个本地通知?