在此之后的讨论中,我遇到了一个不好的接入问题;
一个循环有几个步骤: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); } ];
它也发生了。 如何将您的解决方案适用于本?
提前致谢!
当你创建一个块^{}
语法,它是在栈上创建。 要保留的块的很长一段时间(超过创建它的功能范围内),您必须复制到块堆:
void (^ myBlock)(void) = ^ {
// your block code is here.
};
[IRQ addObject:[[myBlock copy] autorelease]];
如果使用ARC,跳过-autorelease
消息。
的问题是,在栈上创建块的对象。 你需要的时候,你希望他们在他们被宣布被破坏的范围后,可用于块复制到堆,如果该块是不可复制的你。
在这里,你传递一个对象“下跌栈”就是不知道块的方法。 更换
[IRQ addObject:^{ NSLog(@"hello! %@", self); } ];
同
[IRQ addObject:[^{ NSLog(@"hello! %@", self); } copy]];
和EXC_BAD_ACCESS
在这一点上会自动消失。
虽然在大多数情况下,你并不需要复制该块! 一对夫妇的例子:
- 如果你从一个方法返回一个块(“向上堆栈”),ARC会自动复制。
- 如果你调用一个不守块的方法,该块不需要被复制,因为它停留在范围之内。 例如:传递到块
-[NSArray sortedArrayUsingComparator:]
。 - 如果你调用使用该块后的方法,该方法应该采取负责复制块,否则每一个来电者将需要复制该块。 所有方法/从我知道遵循模式的苹果的库中的函数。 例如:在完成块传递到
+[UIView animateWithDuration:options:animations:completion:]
。
看来你传递。在你的例子对象: self
和userName
被过早地释放。 这不是我从块料到的行为。 正如我以前的答案,我希望这个问题是因为太多的保留的!
作为一个测试,你可以尝试:
NSString *userName = [@"James" retain];
[IRQ addObject:^{ NSLog(@"hello %@", userName); } ];
这将是一个内存泄漏,但它会有助于表明,如果该对象被释放。
这是通过一个“保留周期”,其中该块被保持引起self
和self
被保持块。
试试这个:
__block typeof(self) blockSafeSelfReference = self;
[IRQ addObject:^{ NSLog(@"hello! %@", blockSafeSelfReference); } ];
如果使用ARC,使用__unsafe_unretained
代替__block