如果我有一个Foo类声明为:
@interface Foo : NSObject
@property (copy, nonatomic) void (^aBlock)(void);
- (void)bar;
@end
@implementation Foo
- (void)bar {}
@end
我将一个捕获该实例本身的块存储在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()
或者我只是这样做:
Foo *foo = [Foo new];
__weak Foo *weakFoo = foo;
foo.aBlock = ^{
[weakFoo bar];
}
... then somewhere later use foo.aBlock()
添加
__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()
现在,您介绍了一种竞争条件,其中
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;
}
关于objective-c - 解决保留周期:当我们已经拥有__weak * weakSelf时,真的有理由添加__strong * strongSelf吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22996536/