繁体   English   中英

在ARC中,dealloc方法调用包含对self的弱引用的method / block,从而导致weakSelf = nil

[英]In ARC, dealloc method calls method/block that contains weak reference to self result in weakSelf = nil

如标题所述,在ARC模式下,当我使用自引用定义一个块时(避免引用周期较弱):

...
id __weak weakSelf = self;
self.someBlock = ^(){
    if (weakSelf != nil){
        (do something with weakSelf...)
        return NO;
    }
    return YES;
};
...

在dealloc中,我调用该块:

- (void)dealloc {
    ...
    BOOL isNil = self.someBlock();
    ...
}

然后我发现isNil = YES。

当我希望dealloc中的块对self做某事时,这似乎是一个问题。

回调函数中也会发生这种情况,在此不再赘述。

我的解决方案是使用__unsafe_unretained而不是__weak。

但这看起来很丑。

是否有更好的方法来避免在dealloc中出现零自我?

更新的问题:为什么即使弱势self weakSelf ,弱势self也会被否定? dealloc的原因吗?


为了清楚起见,我在下面粘贴了测试代码:

#import <Foundation/Foundation.h>

@interface blockWeak : NSObject

@property (nonatomic, strong) BOOL (^someBlock)();
@property (nonatomic) int num;

- (void)makeBlock;

@end

@implementation blockWeak

- (void)makeBlock
{
    typeof(self) __weak weakSelf = self;
    self.someBlock = ^(){
        typeof(self) strongSelf = weakSelf;
        strongSelf.num = 2;
        return weakSelf == nil?YES:NO;
    };
}

- (void)dealloc
{
    BOOL isNil = self.someBlock();
    if (isNil) {
        NSLog(@"weakSelf is nil.");
    }
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        blockWeak *bw = [[blockWeak alloc] init];
        bw.num = 1;
        [bw makeBlock];
    }
    return 0;
}

您不调用该块。 那将是:

BOOL isNil = self.someBlock();

下面的作品,我认为更干净,因为那时没有提及self 另外,现在并不需要块的返回BOOL ,但是我将其留在了...

#import <Foundation/Foundation.h>

@interface blockWeak : NSObject

@property (nonatomic, copy) BOOL (^someBlock)(blockWeak *);
@property (nonatomic) int num;

- (void)makeBlock;

@end

@implementation blockWeak

- (void)makeBlock
{
    self.someBlock = ^BOOL(blockWeak *object){
        object.num = 2;
        return object == nil?YES:NO;
    };
}

- (void)dealloc
{
    NSLog(@"num = %d", _num);
    BOOL isNil = _someBlock(self);
    if (isNil) {
        NSLog(@"block returned NO");
    } else {
        NSLog(@"block returned YES");
    }
    NSLog(@"num = %d", _num);
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        blockWeak *bw = [[blockWeak alloc] init];
        bw.num = 1;
        [bw makeBlock];
    }
    return 0;
}

输出

num = 1
block returned YES
num = 2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM