@weakify与@strongify

self.block = ^{
        [self myDescription];
    };

在block语句块中,如果需引用self,而self对象中又持有block对象,就会造成循环引用 循环引用(retain cycle) ,导致内存泄露.
一般我们是这么解决的,使用一个 __weak 修饰的weakSelf变量指向self对象,在block中使用weakSelf

__weak typeof(self) weakSelf = self;
    self.block = ^{
        [weakSelf myDescription];
    };

这样写仍然会出问题,因为weakSelf是弱引用,而self一旦释放了,weakSelf可能为nil,比如下面
1 定义一个MyObj对象,它的属性有一个block对象

@interface MyObj : NSObject
@property (nonatomic, copy)void(^block)();
@end

@implementation TestObj

- (void)dealloc {
    NSLog(@"%s",__func__);
}

- (instancetype)init {
    self = [super init];
    if (self) {
        __weak typeof(self) weakSelf = self;
        self.block = ^{
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
       [NSThread sleepForTimeInterval:2];
        NSLog(@"%@",weakSelf);
            });
        };
    }
    return self;
}

@end

2,在其他类中定义一个myFunc方法

- (void)myFunc{
    MyObj *obj = [MyObj new];
    obj.block();
}

执行 myFunc 方法,结果是打印的是(null),因为block里打印的方法是异步执行的,在 NSLog(@”%@”,weakSelf); 这句代码执行之前 myFunc 函数就结束,所以 obj 对象已经被release了。

怎么解决呢?所以再对 weakSelf 做一次 __strong 就可以了:

__weak typeof(self) weakSelf = self;
 self.block = ^{
          __strong typeof(weakSelf) strongSelf = weakSelf;
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
         [NSThread sleepForTimeInterval:2];
          NSLog(@"%@",strongSelf);
            });
        };
}

使用了 __strong 在 strongSelf 变量作用域结束之前,对 weakSelf 有一个引用,防止对象(self)提前被释放。而作用域一过, strongSelf 不存在了,对象(self)也会被释放。

  • 问题
    每次都要写那两条长长的 __weak 和 __strong ,而且在block里用到的self的全部要改成strongSelf,假设把一段很多self的代码拷贝到block里,一个个改成strongSelf就很麻烦

@weakify(self);
[[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
@strongify(self);
[self popViewControllerAnimated:YES];
}];

只要在block外用了@weakify(self);然后再block里写@strongify(self);就可以了,@strongify(self);语句后的的self可以原封不动.
@weakify、@strongify 这两个神奇的宏最终替换了什么东西。
@weakify(self)

@autoreleasepool{} __attribute__((objc_ownership(weak)))__typeof_(self) self_weak_ = (self)

@strongify(self)

__attribute__((objc_ownership(strong))) __typeof__(self) self = self_weak_;
@autoreleasepool {} 是什么?
注意到@weakify(self)中, @ 并不属于宏的一部分,当然你不能平白无故写个@对吧,所以RAC的weakify宏定义机智地给你补了一句 autoreleasepool {} 这样一前一后就变成了啥事都没干的@autoreleasepool {}
__attribute__((objc_ownership(weak)))是什么?
这个就是__weak在编译前被编译器替换的结果,而weakify这个宏最终替换的代码包含有__weak(后面说到),所以编译器再替换就成了__attribute__((objc_ownership(weak)))

weakify、strongify的定义

... 和 __VA_ARGS__ 
看下 NSLog 和 printf ,他们的传入参数有多个,用...表示不确定参数个数,看看NSLog的定义:
NSLog(NSString *format, ...) 
在宏里也可以用 ... 来表示多个参数,而 __VA_ARGS__ 就对应多个参数的部分。

举个例子,你觉得NSLog太难看,想造一个自己的log打印函数,比如MHFLog你就可以这么写:
#define MHFLog(...) NSLog(__VA_ARGS__)
宏连接符 ## :

## 这个符号 会将出现在 ## 左右两边连接的东西起来,举个例子:
宏定义为 #define XLink(n) x ## n ,这宏的意思是把x和传入的n连接起来书写:

#define XLink(n) x ## n
int x1 = 1;
int x2 = 2;
int x3 = 3;
//打印x1 x2 x3
NSLog(@"%d",XLink(1)); //NSlog(@"%zd",x1);
NSLog(@"%d",XLink(2)); //NSlog(@"%zd",x2);
NSLog(@"%d",XLink(3)); //NSlog(@"%zd",x3);

typeof(self) 在block代码块内这样写为什么不会造成循环引用(retain cycle)?

typeof 、 __typeof 、 __typeof__ 这三种写法功能是一样的,这三个函数并不是标准C中规定的,它是一种编译器特性。
/**
 Synthsize a weak or strong reference.

 Example:
    @weakify(self)
    [self doSomething^{
        @strongify(self)
        if (!self) return;
        ...
    }];

 */
#ifndef weakify
    #if DEBUG
        #if __has_feature(objc_arc)
            #define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
        #else
            #define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
        #endif
    #else
        #if __has_feature(objc_arc)
            #define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
        #else
            #define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
        #endif
    #endif
#endif

#ifndef strongify
    #if DEBUG
        #if __has_feature(objc_arc)
            #define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
        #else
            #define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
        #endif
    #else
        #if __has_feature(objc_arc)
            #define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
        #else
            #define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
        #endif
    #endif
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值