先看看__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"];
}
}
新增的自动释放池可以减少内存用量,因为系统会在块的末尾把这些对象回收掉。而上述这些临时对象,正在回收之列。
网友评论