【问题标题】:NSManagedObjectContext executeFetchRequest returns erratic objects, causes EXC_BAD_ACCESS, SIGABRT, etcNSManagedObjectContext executeFetchRequest 返回不稳定的对象,导致 EXC_BAD_ACCESS、SIGABRT 等
【发布时间】:2011-07-12 07:31:36
【问题描述】:

我的猜测是我在这里缺少一些核心数据基础知识,但这里是:

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

在某些情况下,它会返回看似已发布的对象(例如,稍后尝试引用返回结果的几行代码会给出 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;

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

【问题讨论】:

    标签: iphone ios memory core-data reference


    【解决方案1】:

    你基本上是这样做的:

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

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

    【讨论】:

    • 您的星号脚注是解决我的特定问题的关键。我发现我正在使用的数组是由托管对象上下文返回的,我假设这个数组保留了它的对象 - 我只是在它生成后立即循环遍历数组并将每个项目添加到我创建的可变数组中并返回它而不是上下文给我的那个,它解决了这个问题。 “在现实世界中,你不知道什么保留了你的对象”和“保留任何你希望保留的东西是一种很好的做法”是我所需要的。 :) 非常感谢。
    【解决方案2】:

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

    【讨论】:

    • 好电话。不幸的是,它并没有解决问题。但我已经根据你的建议更新了我的代码(让它更干净一些):)
    【解决方案3】:

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

    解决方案:EXC_BAD_ACCESS 总是值得一趟僵尸车道。对内存管理进行尽职调查。

    【讨论】:

      猜你喜欢
      • 2011-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2010-09-15
      相关资源
      最近更新 更多