ObjC:BAD访问时,呼叫块^ {}在后面的功能呢?(ObjC: BAD ACCESS when

2019-07-30 05:20发布

在此之后的讨论中,我遇到了一个不好的接入问题;

一个循环有几个步骤:A,B,C,... X,Y,Z:

-(void)cycle:(float)delta{
[self stepA]
[self stepB]
// etc.
[self stepZ]
}

在某些时候,步骤x执行以下操作:

// IRQ is an NSMutableArray
// Self is a reference to the engine running the cycles
[IRQ addObject:^{ NSLog(@"hello! %@", self); } ];

后来,一步z是处理所有的“延迟”呼吁:

            for (int i = 0; i < [IRQ count]; i++){
                void (^delayedCall)(void) = [IRQ objectAtIndex:i];
                delayedCall();
            }

            [IRQ removeAllObjects];

结果:EXEC_BAD_ACCESS

现在,如果步骤x只增加了普通字符串就像下面没有对象引用,步骤联动z正常工作:

[IRQ addObject:^{ NSLog(@"hello!"); } ];

最后的观察,如果同一步骤中都添加到队列块和迭代队列执行块,然后不会出现问题。 像的基准的一个对象被“丢失”的步骤:方法由?

我不明白,在这方面多,将需要更多的帮助!

编辑:詹姆斯,只是尝试以下,以避免参考cyle:

NSString *userName = @"James";
[IRQ addObject:^{ NSLog(@"hello %@", userName); } ];

它也发生了。 如何将您的解决方案适用于本?

提前致谢!

Answer 1:

当你创建一个块^{}语法,它是在栈上创建。 要保留的块的很长一段时间(超过创建它的功能范围内),您必须复制到块堆:

void (^ myBlock)(void) = ^ {
    // your block code is here.
};
[IRQ addObject:[[myBlock copy] autorelease]];

如果使用ARC,跳过-autorelease消息。



Answer 2:

的问题是,在栈上创建块的对象。 你需要的时候,你希望他们在他们被宣布被破坏的范围后,可用于块复制到堆,如果该块是不可复制的你。

在这里,你传递一个对象“下跌栈”就是不知道块的方法。 更换

[IRQ addObject:^{ NSLog(@"hello! %@", self); } ];

[IRQ addObject:[^{ NSLog(@"hello! %@", self); } copy]];

EXC_BAD_ACCESS在这一点上会自动消失。

虽然在大多数情况下,你并不需要复制该块! 一对夫妇的例子:

  1. 如果你从一个方法返回一个块(“向上堆栈”),ARC会自动复制。
  2. 如果你调用一个不守块的方法,该块不需要被复制,因为它停留在范围之内。 例如:传递到块-[NSArray sortedArrayUsingComparator:]
  3. 如果你调用使用该块后的方法,该方法应该采取负责复制块,否则每一个来电者将需要复制该块。 所有方法/从我知道遵循模式的苹果的库中的函数。 例如:在完成块传递到+[UIView animateWithDuration:options:animations:completion:]


Answer 3:

看来你传递。在你的例子对象: selfuserName被过早地释放。 这不是我从块料到的行为。 正如我以前的答案,我希望这个问题是因为太多的保留的!

作为一个测试,你可以尝试:

NSString *userName = [@"James" retain];
[IRQ addObject:^{ NSLog(@"hello %@", userName); } ];

这将是一个内存泄漏,但它会有助于表明,如果该对象被释放。

这是通过一个“保留周期”,其中该块被保持引起selfself被保持块。

试试这个:

__block typeof(self) blockSafeSelfReference = self;
[IRQ addObject:^{ NSLog(@"hello! %@", blockSafeSelfReference); } ];

如果使用ARC,使用__unsafe_unretained代替__block



文章来源: ObjC: BAD ACCESS when call blocks ^{} in later functions?