NSManagedObjectContext executeFetchRequest返回不稳定的对象,导致EXC_BAD_ACCESS,SIGABRT等

时间:2011-07-12 07:31:37

标签: iphone ios memory core-data reference

我的猜测是我在这里缺少一些核心数据的基本理解,但这里有:

我的应用中有几个提取请求来处理不同事物的检索。在某些情况下,代码运行正常,返回请求的对象。

在某些情况下,它会返回看似已经释放的对象(例如,稍后尝试引用返回结果的几行代码会产生EXC_BAD_ACCESS)。当我在代码中设置各种断点和日志语句并逐步执行时,它还会在代码中的其他位置偶尔获得SIGABRT或EXC_BAD_ACCESS。

在每种情况下,似乎都是在我引用获取请求的结果时。

以下是一个此类获取请求的示例:

// Who am I?
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *signedInPersonId = [defaults stringForKey:@"signedInPersonId"];

// Return (if any) the Request object with given UUID
RequestStrings *r = [[RequestStrings alloc] init];
NSEntityDescription *description = [NSEntityDescription entityForName:r.table_Request inManagedObjectContext:moc];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(UUID == %@) && (dataOwnerId == %@)", UUID, signedInPersonId];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:description];
[request setPredicate:predicate];
NSError *error = nil;

NSArray *requests = [moc executeFetchRequest:request error:&error];

Request *returnRequest = nil;
if (requests != nil) {        
    if ([requests count] > 0) {
        NSLog(@"getRequestWithId - requests array: %@, first: %@", requests, [requests objectAtIndex:0]);
        returnRequest = [requests objectAtIndex:0];
    }
    else {
        returnRequest = nil;
    }
}

[r release];
[request release];
return returnRequest;

P.S。这里有更多信息 在某些情况下,相同的代码将返回所需的对象,或抛出一个异常,指出[NSCFNumber length]是一个无法识别的选择器。不确定相同的实体描述+获取请求如何在一种情况下返回一个数组而在另一种情况下返回一个数字。

3 个答案:

答案 0 :(得分:3)

你基本上是这样做的:

// (1) Create an array of stuff
NSArray *myArray = [NSarray arrayWithObjects:a, b, c, nil];

// (2) Take the first one off
id myObject = [myArray objectAtIndex:0];

// (3) Release everything
[myArray release];

// (4) Return myObject
return myObject;

您只是使用CoreData执行步骤(1)。

步骤(1)返回一个对象数组。保留这些对象的唯一因素是它们所在的数组*。如果释放阵列(步骤3),则将释放其中的所有对象。为什么期望myObject在步骤(4)中仍然存在?

试试这个:

// Make sure that we keep a retain of returnRequest
returnRequest = [[[requests objectAtIndex:0] retain] autorelease];

*对于迂腐的人:我做了一个假设,使我的答案更简单。在现实世界中,你不知道什么是保留你的对象 - 这取决于框架和你的代码。但是,保留您期望保留的任何内容都是很好的做法。

答案 1 :(得分:0)

为什么不在返回前完成所有发布?这应该可以解决您的问题,因为您在创建后立即发布了这些内容。

答案 2 :(得分:0)

@deanWombourne - 很好的建议,我认为你是对的。事实证明我实际上是从一个僵尸崩溃了(当我使用以前获取的托管对象的值时,我没有在以前的视图控制器中使用我自己的setter)。

解决方案:EXC_BAD_ACCESS总值得沿着僵尸车道行驶。对内存管理尽职尽责。