美文网首页
探讨weakSelf、strongSelf、@weakify、@

探讨weakSelf、strongSelf、@weakify、@

作者: cs_mark | 来源:发表于2018-09-26 18:12 被阅读0次

    先看看__strong

    生成对象的时候用alloc/new/copy/mutableCopy等方法。

    当我们声明了一个__strong对象

      id __strong obj = [[NSObject alloc] init];
    

    Clang会把上述代码转换成这个样子

    id __attribute__((objc_ownership(strong))) obj = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
    

    相应会调用

    id obj = objc_msgSend(NSObject, @selector(alloc));
    objc_msgSend(obj,selector(init));
    objc_release(obj);
    
    生成对象的时候不用alloc/new/copy/mutableCopy等方法。
        id __strong obj = [NSMutableArray array];
    

    Clang会把上述代码转换成这个样子

    id __attribute__((objc_ownership(strong))) array = ((NSMutableArray *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("array"));
    

    相应会调用

    id obj = objc_msgSend(NSMutableArray, @selector(array));
    objc_retainAutoreleasedReturnValue(obj);
    objc_release(obj);
    

    __weak的实现原理

    声明一个__weak对象

        id __weak obj = strongObj;
    

    Clang会把上述代码转换成这个样子

    id __attribute__((objc_ownership(none))) obj1 = strongObj;
    

    相应会调用

    id obj ;
    objc_initWeak(&obj,strongObj);
    objc_destoryWeak(&obj);
    

    在block中使用

    我们经常在bolck中使用weakSelf来解决循环引用的问题,而weakSelf之后,无法控制什么时候会被释放,为了保证在block内不会被释放,需要添加__strong。
    在block里面使用的__strong修饰的weakSelf是为了在函数生命周期中防止self提前释放。strongSelf是一个自动变量当block执行完毕就会释放自动变量strongSelf不会对self进行一直进行强引用。

    宏定义的写法

    平时我们使用的写法大致就是

    define WeakSelf __weak typeof(self)weakSelf = self;
    define WeakSelf typeof(self) __weak weakSelf = self;
    
    define StrongSelf __strong __typeof(weakSelf)strongSelf = weakSelf;
    
    

    这里我们具体看看大神是怎么实现这2个宏的。
    在afn中有这么一段代码

    __weak __typeof(self)weakSelf = self;
            [super setCompletionBlock:^ {
                __strong __typeof(weakSelf)strongSelf = weakSelf;
     
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wgnu"
                dispatch_group_t group = strongSelf.completionGroup ?: url_request_operation_completion_group();
                dispatch_queue_t queue = strongSelf.completionQueue ?: dispatch_get_main_queue();
    #pragma clang diagnostic pop
     
                dispatch_group_async(group, queue, ^{
                    block();
                });
     
                dispatch_group_notify(group, url_request_operation_completion_queue(), ^{
                    [strongSelf setCompletionBlock:nil];
                });
            }];
    

    如果不加__strong __typeof(weakSelf)strongSelf = weakSelf 那么bolck 会提前释放,输出:("my name is = (null)")有兴趣的朋友可以自己试一试。

    重点就在dispatch_after这个函数里面。在study()的block结束之后,student被自动释放了。又由于dispatch_after里面捕获的weak的student,根据第二章讲过的weak的实现原理,在原对象释放之后,__weak对象就会变成null,防止野指针。所以就输出了null了。

    strongSelf的目的是因为一旦进入block执行,假设不允许self在这个执行过程中释放,就需要加入strongSelf。block执行完后这个strongSelf 会自动释放,没有不会存在循环引用问题。如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。

    @weakify、@strongify的作用和weakSelf、strongSelf对应的一样。

    @weakify(self) = @autoreleasepool{} weak typeof_ (self) self_weak = self;
    @strongify(self) = @autoreleasepool{} strong typeof_(self) self = self_weak;

    其实@weakify(self) 和 @strongify(self) 就是比我们日常写的weakSelf、strongSelf多了一个@autoreleasepool{}而已。

    而关于@autoreleasepool{}

    执行下面这段代码

    for (int i = 0; i < 999999; i++) {
        NSString *string = @"123";
        string = [string lowercaseString];
        string = [string stringByAppendingString:@"asd"];
    }
    

    你会发现临时对象string在调用完方法后就不再使用了,它们也依然处于存活状态,因为目前它们都在自动释放池里,等待系统稍后进行回收。但自动释放池却要等到该线程执行下一次事件循环时才会清空,这就意味着在执行for循环时,会有持续不断的新的临时对象被创建出来,并加入自动释放池。要等到结束for循环才会释放。在for循环中内存用量会持续上涨,而等到结束循环后,内存用量又会突然下降。

    而如果把循环内的代码包裹在“自动释放池”中,那么在循环中自动释放的对象就会放在这个池,而不是在线程的主池里面。如下:

    for (int i = 0; i < 999999; i++) {
            @autoreleasepool {
                NSString *string = @"123";
                string = [string lowercaseString];
                string = [string stringByAppendingString:@"asd"];
            }        
    }
    

    新增的自动释放池可以减少内存用量,因为系统会在块的末尾把这些对象回收掉。而上述这些临时对象,正在回收之列。

    相关文章

      网友评论

          本文标题:探讨weakSelf、strongSelf、@weakify、@

          本文链接:https://www.haomeiwen.com/subject/ttsjoftx.html