基于块的枚举获取BAD_ACCESS

时间:2013-07-22 21:00:10

标签: objective-c nsarray objective-c-blocks enumeration

我有一个基于块的枚举设置来遍历NSDictionaries数组,如下所示:

__block NSURL *contentURL;

 //This method of enumerating over the array gives the bad_access error
[documents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

    NSString *aName = [(NSDictionary *)obj objectForKey:@"Name"];

    if([aName isEqualToString:name]) {

        contentURL = [NSURL URLWithString:[(NSDictionary *)obj objectForKey:@"Content"]];
        *stop=YES;
    }
}];

NSLog(@"Content URL for issue with name %@ is %@", name, contentURL);

如果我使用此方法,当我尝试在NSLog语句中将其打印出来时,contentURL上会出现EXC_BAD_ACCESS错误。

但是,如果我通过这样的数组枚举:

NSURL *contentURL;

//This method of enumerating over the array works fine
for (NSDictionary *obj in documents) {

    NSString *aName = [obj objectForKey:@"Name"];

    if([aName isEqualToString:name]) {

        contentURL = [NSURL URLWithString:[obj objectForKey:@"Content"]];

    }
}

NSLog(@"Content URL for issue with name %@ is %@", name, contentURL);

一切正常。为什么是这样?

2 个答案:

答案 0 :(得分:3)

我前一段时间遇到过类似的问题。

事实证明,一些基于块的枚举方法将枚举包装在自动释放池中。由于您正在分配一个自动释放的对象,因此在-enumerateObjectsUsingBlock:返回之前会被取消分配。

(我遇到了-[NSDictionary enumerateKeysAndObjectsUsingBlock:的问题,但同样的原则适用于此处)

请改为尝试:

contentURL = [[NSURL alloc] initWithString:[(NSDictionary *)obj objectForKey:@"Content"];

出于兴趣,您使用ARC吗?如果您愿意,我预计会在作业中添加-retain

修改 您正在使用ARC,因此这不是您问题的答案。分配给__block变量将保留该对象(除非您在ARC中遇到错误,这是不太可能的。您使用Apple LLVM 5.0编译时,您提供的代码没有此问题)。

您的问题很可能在其他地方,并且使用便利构造函数的改变只是掩盖了问题。

同样,在枚举期间设置的自动释放池可能会显示代码中其他位置导致的问题。它解释了为什么切换到使用快速枚举似乎可以解决问题,但是像以前一样,它可能只是掩盖了代码中其他地方引起的问题。

我会在这里留下答案,因为有关自动释放池的信息可能仍然与偶然发现此事的人有关。

答案 1 :(得分:0)

如果你正在使用ARC,就像你说的那样,那么你展示的代码就不会产生你描述的问题。你必须在其他地方遇到问题,或者你的代码不像你描述的那样。