美文网首页
探讨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、@

    先看看__strong 生成对象的时候用alloc/new/copy/mutableCopy等方法。 当我们声明了...

  • iOS宏定义

    1 weakself和strongself #ifndef weakify #if DEBUG #ifhas_fe...

  • ObjC的Block中使用weakSelf/strongSelf

    学习block帖子ObjC的Block中使用weakSelf/strongSelf @weakify/@stron...

  • iOS Block 相关

    1.深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用...

  • RN 调 js 核心代码

    ^{RCTJSCExecutor *strongSelf = weakSelf;if (!strongSelf |...

  • 宏定义

    1.weakSelf和strongSelf

  • 不一样的书写样式

    **********************1.block中weakSelf 与 strongSelf******...

  • StrongSelf

    weakSelf : 防止循环引用 strongSelf: 防止释放 需要 强引用weakSelf,主要是处理一...

  • weakSelf/strongSelf

    1.Retain Circle的由来 当A对象里面强引用了B对象,B对象又强引用了A对象,这样两者的retainC...

  • weakSelf & strongSelf

    循环引用 循环引用不做过多的解释,两个对象互相持有对方,谁都无法先被释放掉。循环引用经常是由于使用block而引起...

网友评论

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

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