首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Core-Data NSObjectInaccessibleException NSManagedObject已失效

Core-Data NSObjectInaccessibleException NSManagedObject已失效
EN

Stack Overflow用户
提问于 2011-08-28 22:27:59
回答 2查看 2.3K关注 0票数 1

我有一些代码可以下载JSON形式的课程,解析它们,并将它们放入核心数据中。然后将它们显示在UITableView中。目前,当用户有许多课程时,连接有时会超时。因此,我尝试在课程传入时对其进行解析(使用SBJson),并将其逐个添加到表视图中。

这两者的代码基本上是相同的,但是新的代码会在tableView开始工作时导致崩溃,并出现错误

代码语言:javascript
复制
"Terminating app due to uncaught exception 
'NSObjectInaccessibleException', reason: 'The NSManagedObject with ID:0x5ad0570 <x-coredata://A21AC71F-175B-423D-BF7D-C67BEE094460/Lessons/p18> has been invalidated.'"

我想知道这两个可能导致这个错误的代码清单之间的区别是什么。原始代码在循环中创建每个核心数据对象,但新代码在下载时创建每个核心数据对象。listViewArray是用于填充UITableView的数组。

我使用SBJsonStreamParser和SBJsonStreamParserAdapter来解析传入的Json。

我确实有一个有效的实现(未显示),它基本上在每次接收到新对象时调用下面的原始代码(每次都会运行接收到的对象的整个循环)。不过,我想知道是什么导致了错误,而不仅仅是想让一些东西正常工作。

这是在connectionDidFinishLoading中调用的原始非流代码:

代码语言:javascript
复制
    NSMutableArray *tempListArray = [[NSMutableArray alloc] initWithArray:jsonStreamedData];

    if (listViewArray)
        [listViewArray release];
    listViewArray = [[NSMutableArray alloc] init];

    if(![tempListArray count]){
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Message" message:@"No active lessons " delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alertView show];
        [alertView release];
    }
    else {
        MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
        NSError *error = nil;
        [appDelegate.managedObjectContext reset];

        NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
        for (int i = 0; i < [tempListArray count]; i++) {

            NSFetchRequest *checkRequest = [[NSFetchRequest alloc] init];
            NSEntityDescription *lessonEntity = [NSEntityDescription entityForName:@"Lessons" inManagedObjectContext:managedObjectContext];
            [checkRequest setEntity:lessonEntity];
            NSPredicate *langPredicate = [NSPredicate predicateWithFormat:@"(language = %@)", appDelegate.currentLanguage];
            NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"(username = %@)", appDelegate.userName];
            NSPredicate *idPredicate = [NSPredicate predicateWithFormat:@"(content_Id = %@)", [[tempListArray objectAtIndex:i] valueForKey:@"id"]];
            [checkRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:langPredicate, userPredicate, idPredicate, nil]]];

            NSArray *checkResults = [managedObjectContext executeFetchRequest:checkRequest error:&error];
            [checkRequest release];

            NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
            if ([checkResults count]) {
                Lessons *lessonObj = [checkResults objectAtIndex:0];
                lessonObj.cards_count = [[tempListArray objectAtIndex:i] valueForKey:@"cards_count"];
                lessonObj.mTitle = [[tempListArray objectAtIndex:i] valueForKey:@"title"];
                lessonObj.sound_Url = [[tempListArray objectAtIndex:i] valueForKey:@"audio_url"];
                lessonObj.mId = [NSNumber numberWithInt:i];
                [tempDict setValue:lessonObj forKey:@"lesson"];
                [tempDict setValue: [[tempListArray objectAtIndex:i]  objectForKey:@"image_url"] forKey:@"image_url"];
                [listViewArray addObject:tempDict];

            }
            else {

                Lessons *newLesson = (Lessons *)[NSEntityDescription insertNewObjectForEntityForName:@"Lessons" inManagedObjectContext:appDelegate.managedObjectContext];
                newLesson.cards_count = [[tempListArray objectAtIndex:i] valueForKey:@"cards_count"];
                newLesson.mTitle = [[tempListArray objectAtIndex:i] valueForKey:@"title"];
                newLesson.sound_Url = [[tempListArray objectAtIndex:i] valueForKey:@"audio_url"];
                newLesson.content_Id = [[tempListArray objectAtIndex:i] valueForKey:@"id"];
                newLesson.username = appDelegate.userName;
                newLesson.language = appDelegate.currentLanguage;
                newLesson.mId = [NSNumber numberWithInt:i];
                [tempDict setValue:newLesson forKey:@"lesson"];
                [tempDict setValue: [[tempListArray objectAtIndex:i]  objectForKey:@"image_url"] forKey:@"image_url"]; 
                [listViewArray addObject:tempDict];

            }
            [tempDict release];
            tempDict = nil;
        }


        if (![appDelegate.managedObjectContext save:&error]) {
            NSLog(@"Core Data Error - %@", [error localizedDescription]);

        }   

        //      NSMutableArray *tempArray = [NSMutableArray arrayWithArray:listViewArray];
        //      [listViewArray removeAllObjects];
        //      [listViewArray addObjectsFromArray:[[tempArray reverseObjectEnumerator] allObjects]];
        //      tempArray = nil;
    }
    [tempListArray release];
}
[mListsTableView reloadData];

下面是崩溃的代码,在parser:foundObject中调用:循环代码已被删除,因为每次下载新的Json对象时都会调用此代码。

代码语言:javascript
复制
    [jsonStreamedData addObject:dict];
    if (!listViewArray)
        listViewArray = [[NSMutableArray alloc] init];

    MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSError *error = nil;
    [appDelegate.managedObjectContext reset];

    NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;

    NSFetchRequest *checkRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *lessonEntity = [NSEntityDescription entityForName:@"Lessons" inManagedObjectContext:managedObjectContext];
    [checkRequest setEntity:lessonEntity];
    NSPredicate *langPredicate = [NSPredicate predicateWithFormat:@"(language = %@)", appDelegate.currentLanguage];
    NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"(username = %@)", appDelegate.userName];
    NSPredicate *idPredicate = [NSPredicate predicateWithFormat:@"(content_Id = %@)", [dict valueForKey:@"id"]];
    [checkRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:langPredicate, userPredicate, idPredicate, nil]]];

    NSArray *checkResults = [managedObjectContext executeFetchRequest:checkRequest error:&error];
    [checkRequest release];

    NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];

    if ([checkResults count]) {
        Lessons *lessonObj = [checkResults objectAtIndex:0];
        lessonObj.cards_count = [dict valueForKey:@"cards_count"];
        lessonObj.mTitle = [dict  valueForKey:@"title"];
        lessonObj.sound_Url = [dict valueForKey:@"audio_url"];
        lessonObj.mId = [NSNumber numberWithInt:jsonStreamedData.count - 1]; // This should be equivalent to i from the loop in the first code
        [tempDict setValue:lessonObj forKey:@"lesson"];
        [tempDict setValue: [dict objectForKey:@"image_url"] forKey:@"image_url"];
        [listViewArray addObject:tempDict];

    }
    else {

        Lessons *newLesson = (Lessons *)[NSEntityDescription insertNewObjectForEntityForName:@"Lessons" inManagedObjectContext:appDelegate.managedObjectContext];
        newLesson.cards_count = [dict valueForKey:@"cards_count"];
        newLesson.mTitle = [dict valueForKey:@"title"];
        newLesson.sound_Url = [dict valueForKey:@"audio_url"];
        newLesson.content_Id = [dict valueForKey:@"id"];
        newLesson.username = appDelegate.userName;
        newLesson.language = appDelegate.currentLanguage;
        newLesson.mId = [NSNumber numberWithInt:jsonStreamedData.count - 1];
        [tempDict setValue:newLesson forKey:@"lesson"];
        [tempDict setValue: [dict  objectForKey:@"image_url"] forKey:@"image_url"]; 
        [listViewArray addObject:tempDict];

    }

    [tempDict release];
    tempDict = nil;

    if (![appDelegate.managedObjectContext save:&error]) {
        ALog(@"Core Data Error - %@", [error localizedDescription]);
    }   

    //  NSMutableArray *tempArray = [NSMutableArray arrayWithArray:listViewArray];
    //  [listViewArray removeAllObjects];
    //  [listViewArray addObjectsFromArray:[[tempArray reverseObjectEnumerator] allObjects]];
    //  tempArray = nil;
//[self getListsLocally];
[mListsTableView reloadData];

最后,这里是使用第二个清单时崩溃的实际部分,在tableView中:cellForRowAtIndexPath:顺便说一下,当行==为1而不是行== 0时,它会崩溃。出于某种原因,第0行没问题...当然,它从来没有机会加载其他行。

代码语言:javascript
复制
        titleLabel.text = [[[listViewArray objectAtIndex:indexPath.row] valueForKey:@"lesson"] valueForKey:@"mTitle"]; // CRASH!
        labelCards.text = [NSString stringWithFormat:@"%@ Cards", [[[listViewArray objectAtIndex:indexPath.row]  valueForKey:@"lesson"] valueForKey:@"cards_count"]];

        if([[listViewArray objectAtIndex:indexPath.row] objectForKey:@"userImageObj"] == nil){
            mImageView.backgroundColor = [UIColor grayColor];
            if ([[listViewArray objectAtIndex:indexPath.row] objectForKey:@"isThreadLaunched"] == nil) {
                [NSThread detachNewThreadSelector:@selector(loadImagesInBackground:) toTarget:self withObject:[NSNumber numberWithInt:indexPath.row]];
                [[listViewArray objectAtIndex:indexPath.row] setObject:@"Yes" forKey:@"isThreadLaunched"];
            }
        }else {
            mImageView.image = [[listViewArray objectAtIndex:indexPath.row] objectForKey:@"userImageObj"];
        }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-30 04:31:54

当您在运行fetch之前立即在managedObjectContext上调用reset时,很可能会发生对象无效。调用reset会使内存中的对象无效,但在保存之前不会删除它们。如果无效的托管对象由另一个对象(如数组)保留,那么它将以无效的形式保存到保存之后。运行fetch时,fetch将返回无效的对象,当您尝试访问这些对象的某个属性时,这些对象会导致错误

reset是在与撤消管理器一起使用时调用的。它不是一个通用的“擦除上下文”调用。如果您想删除已有的对象,您需要获取它们并显式删除它们。

您的代码还存在一些其他问题。您可以在checkRequest数组上调用release,即使您没有创建它。这可能会导致数组随机消失。同样,listViewArray看起来是一个类属性,但您从不使用访问器形式,例如self.listViewArray来确保适当的保留。

票数 3
EN

Stack Overflow用户

发布于 2011-08-29 06:48:13

最可能的原因是解析器没有在主线程上运行,而你在主线程和解析器之间使用相同的ManagedObjectContext -你不能这样做-保证会导致各种奇怪的行为。

您需要在解析器中创建一个新的ManagedObjectContext,并将其与主线程的ManagedObjectContext的persistentStore相关联

CoreData框架在这一点上非常清楚-您不能跨线程边界共享ManagedObjectContext

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7221561

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档