_____ _____ _____ _____
/\ \ /\ \ /\ \ /\ \
/::\____\ /::\ \ /::\ \ /::\____\
/:::/ / /::::\ \ /::::\ \ /:::/ /
/:::/ _/___ /::::::\ \ /::::::\ \ /:::/ /
/:::/ /\ \ /:::/\:::\ \ /:::/\:::\ \ /:::/ /
/:::/ /::\____\ /:::/__\:::\ \ /:::/__\:::\ \ /:::/____/
/:::/ /:::/ / /::::\ \:::\ \ /::::\ \:::\ \ /::::\ \
/:::/ /:::/ _/___ /::::::\ \:::\ \ /::::::\ \:::\ \ /::::::\____\________
/:::/___/:::/ /\ \ /:::/\:::\ \:::\ \ /:::/\:::\ \:::\ \ /:::/\:::::::::::\ \
|:::| /:::/ /::\____\/:::/__\:::\ \:::\____\/:::/ \:::\ \:::\____\/:::/ |:::::::::::\____\
|:::|__/:::/ /:::/ /\:::\ \:::\ \::/ /\::/ \:::\ /:::/ /\::/ |::|~~~|~~~~~
\:::\/:::/ /:::/ / \:::\ \:::\ \/____/ \/____/ \:::\/:::/ / \/____|::| |
\::::::/ /:::/ / \:::\ \:::\ \ \::::::/ / |::| |
\::::/___/:::/ / \:::\ \:::\____\ \::::/ / |::| |
\:::\__/:::/ / \:::\ \::/ / /:::/ / |::| |
\::::::::/ / \:::\ \/____/ /:::/ / |::| |
\::::::/ / \:::\ \ /:::/ / |::| |
\::::/ / \:::\____\ /:::/ / \::| |
\::/____/ \::/ / \::/ / \:| |
sqi出品 \/____/ \/____/ \|___|
在 Objective-C 中,weak
和 __weak
都与 ARC(Automatic Reference Counting,自动引用计数)相关,并且它们用于描述对象的弱引用。但是,它们在语法和上下文中有一些微妙的差异。
-
weak
:weak
是属性修饰符,用于在类接口(.h
或.m
文件的类扩展中)中声明属性。- 当一个对象被声明为
weak
属性时,它不会增加对象的引用计数。这意味着当没有其他强引用指向该对象时,该对象可以被安全地释放,而无需担心循环引用。 - 使用
weak
的常见场景是在代理(delegate)或回调闭包(block)中,以避免循环引用。 - 示例:
objective-c@property (nonatomic, weak) id<SQIProtocol> delegate; @property (nonatomic, weak) SQICallback callback;
-
__weak
:__weak
是类型修饰符,用于声明对象的弱引用。- 示例:
objective-c__weak SQIClass *weakVariable = someObject;
- 在 block 中,如果你需要捕获一个外部对象, 同时要避免循环引用,你应该使用
__weak
来声明一个弱引用,并在 block 内部使用它。 - 如果该外部对象可能在 block 的生命周期内被释放,但你希望确保在访问它之前它仍然有效时,可以使用
__strong
来临时持有强引用(在 block 或方法内部)。这通常被称为"弱-强舞蹈"(weak-strong dance)。 - 示例:
objc@interface MyObject : NSObject - (void)performBlockOperation; @end @implementation MyObject - (void)performBlockOperation { // 使用 __weak 创建一个对 self 的弱引用 __weak MyObject *weakSelf = self; // 创建一个 block,并在其中执行一些操作 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { // 在 block 内部,使用 weakSelf 可能会遇到它已经被释放的情况 // 因此,我们使用一个局部强引用来确保对象在 block 执行期间存在 MyObject *strongSelf = weakSelf; if (strongSelf) { // 现在我们可以安全地使用 strongSelf,因为即使 self 在其他地方被释放, // 在这个 block 执行期间,strongSelf 仍然指向它 // 执行一些操作... NSLog(@"Performing operation on %@", strongSelf); // 假设我们有一个 completion block,并且我们想在完成后调用它 // 我们同样需要确保在调用它时 strongSelf 仍然存在 dispatch_async(dispatch_get_main_queue()) { if (strongSelf) { // 在主线程上执行完成操作... NSLog(@"Operation completed on %@", strongSelf); } }; } }; } @end
-
共同点:
- 都不能用于非 Objective-C 对象(如 C 结构或 C++ 对象),因为 ARC 仅管理 Objective-C 对象的生命周期。
- 都不会增加对象的引用计数, 当对象的引用计数变为零时,对象将被释放,而弱引用将自动被置为 nil。