Sta*_*ich 2 objective-c objective-c-blocks automatic-ref-counting
如果我有一个类Foo声明如下:
@interface Foo : NSObject
@property (copy, nonatomic) void (^aBlock)(void);
- (void)bar;
@end
@implementation Foo
- (void)bar {}
@end
Run Code Online (Sandbox Code Playgroud)
我在Foo实例中存储了一个捕获此实例的块:
Foo *foo = [Foo new];
__weak Foo *weakFoo = foo;
foo.aBlock = ^{
__strong Foo *strongFoo = weakFoo; <--- does this __strong Foo * really makes sense?
[strongFoo bar];
}
... then somewhere later use foo.aBlock()
Run Code Online (Sandbox Code Playgroud)
或者我只是这样做:
Foo *foo = [Foo new];
__weak Foo *weakFoo = foo;
foo.aBlock = ^{
[weakFoo bar];
}
... then somewhere later use foo.aBlock()
Run Code Online (Sandbox Code Playgroud)
添加是否__strong *strongFoo = weakFoo有意义还是仅仅[weakFoo bar]在块内使用?
在你的例子中,并不是必须再次在块内部进行强引用:weakFoo将是nil并且方法未被调用,或者它是有效的引用,并且在该调用的持续时间内保持有效.
但请考虑以下代码段:
Foo *foo = [Foo new];
__weak Foo *weakFoo = foo;
foo.aBlock = ^{
[weakFoo bar];
[weakFoo baz];
}
... then somewhere later use foo.aBlock()
Run Code Online (Sandbox Code Playgroud)
现在你引入了竞争条件,其中weakFoo第一次调用有效,但nil第二次调用有效.这几乎不是你想要的.在这种情况下__strong Foo *foo = weakFoo;,请确保两个调用都具有相同的值.
编辑:
以下是如何触发此类竞争条件的示例:
@interface BlockHolder : NSObject
@property (nonatomic, copy) void(^block)(void);
@end
@implementation BlockHolder
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
BlockHolder *holder = [[BlockHolder alloc] init];
__weak BlockHolder *weakHolder = holder;
holder.block = ^{
for (int i = 0; i < 10; i++) {
NSLog(@"weakHolder is %@", weakHolder);
sleep(1);
}
};
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, holder.block);
sleep(2); // give the queue some time to start executing the block
holder = nil;
dispatch_sync(queue, ^{}); // wait for the queue to finish
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
272 次 |
| 最近记录: |