weakSelf 运用 strongSelf来解决block的循环引用
SDWebImage 中有一段源码:
#if SD_UIKIT Class UIApplicationClass = NSClassFromString(@"UIApplication"); BOOL hasApplication = UIApplicationClass && [UIApplicationClass respondsToSelector:@selector(sharedApplication)]; if (hasApplication && [self shouldContinueWhenAppEntersBackground]) { __weak __typeof__ (self) wself = self; UIApplication * app = [UIApplicationClass performSelector:@selector(sharedApplication)]; self.backgroundTaskId = [app beginBackgroundTaskWithExpirationHandler:^{ __strong __typeof (wself) sself = wself; if (sself) { [sself cancel]; [app endBackgroundTask:sself.backgroundTaskId]; sself.backgroundTaskId = UIBackgroundTaskInvalid; } }]; } #endif
// AFNetworking 中 AFNetworkReachabilityManager.m 的一段代码 __weak __typeof(self)weakSelf = self; AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { __strong __typeof(weakSelf)strongSelf = weakSelf; strongSelf.networkReachabilityStatus = status; if (strongSelf.networkReachabilityStatusBlock) { strongSelf.networkReachabilityStatusBlock(status); } };
我们用的比较多的 解决循环引用的问题, 在block中 用到对象内部的属性、实例变量的时候要用weakSelf 访问,但是为什么block 内部又用到strongSelf 呢?
大部分情况下,只在block中使用weakSelf 是没有问题的,通常情况下我们只在block中做一个任务,执行完之后回调,但是如果我们要在block中做多个任务,而且第一个任务执行完有可能调用者会释放了selfl, 那么 第二个任务执行时就有可能报错, 若果self所指的对象已经被释放,但是没有被置空,再用这个对象发消息,等于产生了野指针,EXC_BREAKPOINT 错误;
提示:nil 可以接受任何消息,但是不能发送消息哦😯,可以做发消息的操作,但是nil 是发不出去消息的,消息发送给nil,它不会再做转发也是这个道理。
1 2 3 4 5 6 7 8 9 10 | //clang给出的实例代码:<br> __weak __typeof__(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [weakSelf doSomething]; });<br> //clang 的文档表示,在 doSomething 内,weakSelf 不会被释放。但,下面的情况除外: __weak __typeof__( self ) weakSelf = self ; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [weakSelf doSomething]; [weakSelf doOtherThing]; }); |
在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放,
1 2 3 4 5 6 7 | //于是,strongSelf 就派上用场了: __weak __typeof__( self ) weakSelf = self ; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ __strong __typeof( self ) strongSelf = weakSelf; [strongSelf doSomething]; [strongSelf doOtherThing]; }); |
__strong 确保strongSelf在block中不会被释放。
所以就能理解SDWebImage中的那段代码,block在实现的过程中会对wself进行一次强引用,是为了防止在block还未执行完毕,wself在其他线程中被释放,使得wself为nil。
https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具