__weak引用和__block引用之间有什么区别?
__weak引用和__block引用之间有什么区别?
我正在阅读Xcode的文档,以下是其中一个让我困惑的地方:
__block typeof(self) tmpSelf = self; [self methodThatTakesABlock:^ { [tmpSelf doSomething]; }];
以下是从文档中复制的内容:
块会对其捕获的变量形成强引用。如果在块内使用
self
,块会对self
形成强引用,所以如果self
也对块形成强引用(通常如此),会导致强引用循环。为了避免循环,你需要在块外创建一个弱引用(或__block
引用)指向self,就像上面的示例一样。
我不明白'a weak (or __block
)'是什么意思?
在这里,__block typeof(self) tmpSelf = self;
和__weak typeof(self) tmpSelf = self;
是完全一样的吗?
我在文档中找到另一段内容:
注意:在垃圾回收环境中,如果将
__weak
和__block
修饰符同时应用于一个变量,则块不会确保该变量保持存在。
所以,我完全困惑了。
在Objective-C中,__weak和__block是用于处理对象在block中的引用关系的两个关键字。在ARC(自动引用计数)模式下,__weak和__block可以帮助解决block中循环引用的问题。
循环引用是指在block中使用了外部对象的引用,并且该对象又持有了block,从而形成了一个循环引用的关系。这种情况下,block和对象会相互持有对方,导致它们都无法被释放,从而造成内存泄漏。
在ARC模式下,默认情况下,__block修饰的对象会被retain,即会增加其引用计数。这样就会导致block和对象相互引用,从而形成循环引用。为了避免这种情况的发生,可以使用__weak关键字来修饰对象的引用。__weak修饰的对象不会增加其引用计数,当对象被释放后,__weak修饰的引用会自动设置为nil,避免了循环引用的问题。
然而,__weak关键字只在支持iOS 5及以上版本的系统中才可用。如果需要支持iOS 4或OS X v10.6等早期版本的系统,可以使用__block关键字,并将其值设置为nil来打破循环引用。
除了使用__weak和设置__block值为nil之外,还可以使用__unsafe_unretained关键字来达到和__block一样的效果。__unsafe_unretained关键字表示不增加对象的引用计数,但是使用这个关键字需要注意,因为一旦对象被释放,引用就会变成野指针,访问野指针会导致程序崩溃,所以使用__unsafe_unretained关键字需要谨慎。因此,推荐使用__weak或设置__block值为nil来避免循环引用的问题。
__weak关键字和__block关键字都可以用于解决block中循环引用的问题。__weak关键字适用于支持iOS 5及以上版本的系统,而__block关键字则适用于早期版本的系统。使用__weak关键字可以避免循环引用并自动设置为nil,而使用__block关键字需要手动将其值设置为nil来打破循环引用。此外,还可以使用__unsafe_unretained关键字,但需要注意野指针的问题。
__block和__weak引用之间的区别是什么?
自文档中关于__block的说明:
__block变量存储在变量的词法作用域和在变量的词法作用域内声明或创建的所有块和块副本之间共享的存储中。因此,如果在该框架内声明的块的任何副本在框架结束后仍然存在(例如,通过在某个地方排队等待以供以后执行),则存储将在堆栈帧的销毁之后继续存在。给定词法作用域中的多个块可以同时使用共享变量。
自文档中关于__weak的说明:
__weak指定了一个不会保持所引用对象存活的引用。当没有强引用指向该对象时,弱引用会被设置为nil。
所以它们在技术上是不同的东西。__block用于阻止变量从外部作用域复制到块作用域中,而__weak是一种自限定的弱指针。
请注意,我说的是技术上的区别,因为对于你的情况,它们将(几乎)做同样的事情。唯一的区别是是否使用ARC。如果您的项目使用ARC且仅适用于iOS4.3及以上版本,请使用__weak。它确保如果全局作用域引用在某种方式下释放,引用将被设置为nil。如果您的项目不使用ARC或适用于较旧的操作系统版本,请使用__block。
这里有一个微妙的区别,请确保您理解它。
编辑:谜题的另一部分是__unsafe_unretained。这个修饰符几乎与__weak相同,但适用于4.3之前的运行时环境。然而,它不会被设置为nil,并且可能导致悬空指针。
这在使用ARC的iOS7上是否仍然适用?我运行了一个分析器,即使我没有使用__block或__weak并在块中引用self,我看到我的控制器也被释放了。
对于想要查看文档的人:developer.apple.com/library/ios/releasenotes/ObjectiveC/…,developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
怎么样才能同时使用它们呢?__block _weak NSString *strEg;
?
在使用block时,如果需要在block中引用self,应该使用__weak关键字,而不是__block关键字,因为使用__block关键字有可能会导致self被retain。
如果需要在block中使用strong self,可以按照下面的方式进行操作:
__weak typeof(self) *weakSelf = self; [self methodThatTakesABlock:^{ if (weakSelf) { __strong typeof(self) *strongSelf = weakSelf; [strongSelf doSomething]; } }];
在上述代码中,首先使用__weak关键字创建了一个对self的弱引用weakSelf。然后在block中使用了weakSelf,如果weakSelf不为nil,说明self仍然存在,这时使用__strong关键字再次创建一个对self的强引用strongSelf,并通过strongSelf调用了doSomething方法。这样做的目的是避免在block中使用self时,由于block的延迟执行导致self被retain而造成的循环引用问题。