首页 文章

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

提问于
浏览
1

正如 Headers 所述,在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中的自我弱?

Updated Question: 为什么 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;
}

2 回答

  • 1

    下面的作品,在我看来更清晰,因为没有提及 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;
    }
    

    Output

    num = 1
    block returned YES
    num = 2
    
  • 1

    你不打电话给那个街区 . 那将是:

    BOOL isNil = self.someBlock();
    

相关问题