系统需要跟踪存储指向对象的弱指针的每个内存地址。为什么?因为如果要释放对象(其内存将被释放),所有这些指针必须设置为nil
第一的。这就是弱指针的特殊之处:它们不保留对象(不让它们保持活动状态),但它们也永远不是悬空指针(永远不会指向以前的、现在已死的对象的内存地址);如果物体死亡,它们就会变成nil
。因此,每当弱引用的值发生变化时,系统必须首先告诉全局弱指针跟踪管理器删除该内存地址过去记录的信息(如果有的话),然后在对象改变后记录新的信息。不用说,整个事情必须是线程安全的,因此涉及(稍微昂贵的)锁定。
__weak id x;
// ...
x = anObject;
// ...
x = anotherObject;
// ....
x = nil;
事实上(不是真的,只是为了让大家理解这个概念):
__weak id x;
// ...
[WeakPointerTrackingManager lock];
x = anObject;
[WeakPointerTrackingManager var:&x pointsTo:anObject];
[WeakPointerTrackingManager unlock];
// ...
[WeakPointerTrackingManager lock];
x = anotherObject;
[WeakPointerTrackingManager var:&x pointsTo:anotherObject];
[WeakPointerTrackingManager unlock];
// ...
[WeakPointerTrackingManager lock];
x = nil;
[WeakPointerTrackingManager deleteInfoForVar:&x];
[WeakPointerTrackingManager unlock];
assign
没有做那样的事情。只是存储对对象的引用,而不增加对象保留计数器。然而,如果对象死亡,assign
变量仍然指向对象所在的内存地址used为了活着。如果您现在向这个不存在的对象发送消息,您的应用程序可能会崩溃或可能发生其他未定义的事情。
但说实话,每个执行 100,000 次 setDelegate 调用的应用程序在设计上都被破坏了。我想不出任何有意义的严肃用例。在这里可能有更好的方法来完成您想做的任何事情。
仅供记录,访问弱变量也很昂贵。
__weak id x;
// ...
[x sendMessage];
// ...
__strong id y; // Strong is optional,
// vars are strong by default
y = x;
事实上(不是真的):
__weak id x;
// ...
__strong id tmp;
[WeakPointerTrackingManager lock];
tmp = [x retain];
[WeakPointerTrackingManager unlock];
[tmp sendMessage];
[tmp release];
// ...
__strong id y;
[WeakPointerTrackingManager lock];
y = [x retain];
[WeakPointerTrackingManager unlock];