如果我有一个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/

10-13 03:49