<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>mikeash.com pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html comments</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>mikeash.com Recent Comments</description><lastBuildDate>Thu, 18 Jun 2026 04:50:30 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Minh Nguyen - 2021-05-25 04:26:22</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>It is state that: 
&lt;br /&gt;
&lt;br /&gt;- (void)setFoo: (id)newFoo
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_foo = newFoo;
&lt;br /&gt;}
&lt;br /&gt;Because the setter does not use retain, the reference does not keep the new object alive. It will stay alive as long as it's retained by other references, of course. But once those go away, the object will be deallocated even if _foo still points to it.”
&lt;br /&gt;
&lt;br /&gt;Excerpt From: Mike Ash. “The Complete Friday Q&amp;amp;A: Volume 1.” Apple Books. 
&lt;br /&gt;
&lt;br /&gt;But in ARC, I think an instant variable hold a strong reference. Which means that _foo keep hold of the memory of newFoo, right. 
&lt;br /&gt;Please explain me this ? </description><guid isPermaLink="true">2f41e66e9a3330fd6a01347ef5a23e8b</guid><pubDate>Tue, 25 May 2021 04:26:22 GMT</pubDate></item><item><title>Keith - 2015-09-14 20:18:20</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>In &lt;i&gt;CustomSubclassRelease&lt;/i&gt;, shouldn't &lt;i&gt;WhileLocked&lt;/i&gt; surround the entire function? The call to &lt;i&gt;GetRealSuperclass&lt;/i&gt; calls &lt;i&gt;GetCustomSubclass&lt;/i&gt; which accesses the shared variable &lt;i&gt;gCustomSubclasses&lt;/i&gt;.</description><guid isPermaLink="true">f4b7724befbf5276aa8ba6b1a167acca</guid><pubDate>Mon, 14 Sep 2015 20:18:20 GMT</pubDate></item><item><title>Larry - 2015-01-05 14:08:50</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Can this be used for references in UIKit frameworks such as UIGestureRecognizer that may be internally referencing their delegate properties by iVars?</description><guid isPermaLink="true">7b86f08c5e58b3c5f63e572665fb3140</guid><pubDate>Mon, 05 Jan 2015 14:08:50 GMT</pubDate></item><item><title>mikeash - 2013-05-29 14:46:49</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>The problem with swizzling &lt;code&gt;dealloc&lt;/code&gt; is that it will affect every instance of that class, even ones that are not weakly referenced.
&lt;br /&gt;
&lt;br /&gt;For a worst case scenario, consider allocating a plain &lt;code&gt;NSObject&lt;/code&gt; instance, and then creating a weak reference to it. With that approach, you've now swizzled &lt;code&gt;-[NSObject dealloc]&lt;/code&gt;, meaning that &lt;i&gt;every single object in the system&lt;/i&gt; is going through custom code, causing a potentially large performance impact, and increasing the chances of an unfortunate interaction with other code.</description><guid isPermaLink="true">93a78f555e194ae90e36c1d588d9420a</guid><pubDate>Wed, 29 May 2013 14:46:49 GMT</pubDate></item><item><title>François Lamboley - 2013-05-29 10:26:41</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Great article! However, instead of isa-swizzling, couldn't you have used &lt;i&gt;method_exchangeImplementations()&lt;/i&gt; for the dealloc and release methods? You can call the original implementations from your implementations.
&lt;br /&gt;It seems highly easier to use rather than creating a dynamic subclass, and may solve all of the KVO/CF problems.</description><guid isPermaLink="true">c270d1d381e0bc412e1ed09573eb3bef</guid><pubDate>Wed, 29 May 2013 10:26:41 GMT</pubDate></item><item><title>mikeash - 2013-04-03 14:49:49</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>A recursive lock is functionally identical to a lock that ignores locks/unlock pairs on a thread that already has the lock.</description><guid isPermaLink="true">83e6fa31025b24e16c2bc2fd589a956f</guid><pubDate>Wed, 03 Apr 2013 14:49:49 GMT</pubDate></item><item><title>René Bertin - 2013-03-29 16:26:58</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Probably a naive question: why use a recursive (global) mutex? Just so you can lock/release it from a thread that already owns a lock on it? Is that better than a mutex variant which makes a lock and the matching release noops when executed by a thread that already has the lock?</description><guid isPermaLink="true">f953996f2fcac121e3e4633fa9a939a1</guid><pubDate>Fri, 29 Mar 2013 16:26:58 GMT</pubDate></item><item><title>mikeash - 2011-10-03 03:42:29</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Yep, that code looks good. In fact, this is a fairly common use case for this library in my experience. It's really easy to make retain cycles with blocks, and hard to deal with non-zeroing weak references in their place. Zeroing weak references make everything much easier.</description><guid isPermaLink="true">d08df60dca66f16765aed6867f851b08</guid><pubDate>Mon, 03 Oct 2011 03:42:29 GMT</pubDate></item><item><title>Ben G. - 2011-10-02 23:53:02</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Mike, this is some fascinating stuff.
&lt;br /&gt;
&lt;br /&gt;Just so I'm sure I understand the interaction of MAZeroingWeakRef and blocks' implicit retaining behavior, is the following a valid way to create a block that:
&lt;br /&gt;
&lt;br /&gt;1) References self or an ivar of self, and
&lt;br /&gt;2) Can be copied and stored inside self (or an object retained by self) without creating a retain cycle, and
&lt;br /&gt;3) No-ops if self is dealloc'ed before the block is invoked (say, via a copy stored in another object)
&lt;br /&gt;
&lt;br /&gt;?
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;@interface Foo : NSObject
&lt;br /&gt;@property (copy) void (^block)();
&lt;br /&gt;@end
&lt;br /&gt;
&lt;br /&gt;@implementation Foo
&lt;br /&gt;
&lt;br /&gt;@synthesize block = _block;
&lt;br /&gt;
&lt;br /&gt;- (void)foo {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;MAZeroingWeakRef* weakSelf = [[[MAZeroingWeakRef alloc] initWithTarget:self] autorelease];
&lt;br /&gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;self.block = ^{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[[weakSelf target] bar];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;};
&lt;br /&gt;}
&lt;br /&gt;
&lt;br /&gt;- (void)dealloc {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;self.block = nil;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;[super dealloc];
&lt;br /&gt;}
&lt;br /&gt;
&lt;br /&gt;@end
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;</description><guid isPermaLink="true">e8b0f782ac5314669b9c2b725e56df41</guid><pubDate>Sun, 02 Oct 2011 23:53:02 GMT</pubDate></item><item><title>mikeash - 2011-03-21 19:34:33</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>I'm not sure if I've understood you correctly, but any class methods that you don't override will go to the parent class's implementation, since inheritance works at the class level as well as the instance level.</description><guid isPermaLink="true">ae9e6c6912c676fdcbb23535710c1ca9</guid><pubDate>Mon, 21 Mar 2011 19:34:33 GMT</pubDate></item><item><title>mark - 2011-03-21 18:52:56</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Is there anyway to forward class messages to the parent class when a dynamic subclass is created? I'm using resolveInstanceMethod: to support dynamic properties. I've hacked the code to call just that one, but there might be other class methods that no longer work properly once a dynamic subclass is created.</description><guid isPermaLink="true">4ad14cf38abb5fd760f85fb521b4d84d</guid><pubDate>Mon, 21 Mar 2011 18:52:56 GMT</pubDate></item><item><title>mikeash - 2011-03-16 20:57:14</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>otx is really useful. Its annotations are a huge help for bridging the gap between seeing assembly as gibberish and understanding it top to bottom.</description><guid isPermaLink="true">e4c220a3f0e3baf8e1295e58ebe176b6</guid><pubDate>Wed, 16 Mar 2011 20:57:14 GMT</pubDate></item><item><title>Chase - 2011-03-16 18:58:12</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thanks. I got to step 5, and was lost thereafter. Thanks for the pointer to otx, and thanks for giving us so many useful classes!</description><guid isPermaLink="true">c51b6e78ba162845c881443c77b428c8</guid><pubDate>Wed, 16 Mar 2011 18:58:12 GMT</pubDate></item><item><title>mikeash - 2011-03-16 17:48:20</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Here's a rough reconstruction of my steps.
&lt;br /&gt;
&lt;br /&gt;1. Run the test, watch it crash. Notice that it's crashing because it's accessing a deallocated object.
&lt;br /&gt;2. Something must be going wrong with &lt;code&gt;CustomSubclassDealloc&lt;/code&gt; to cause the weak reference not to be zeroed. Put a breakpoint there to see what happens.
&lt;br /&gt;3. Run the test again, breakpoint is not hit. Odd.
&lt;br /&gt;4. Add a stub &lt;code&gt;dealloc&lt;/code&gt; method to &lt;code&gt;KVOTarget&lt;/code&gt; to see if &lt;i&gt;that&lt;/i&gt; is firing. Breakpoint on that to see what happens.
&lt;br /&gt;5. That breakpoint is hit. It is not being called from &lt;code&gt;CustomSubclassDealloc&lt;/code&gt;, but rather from a private Foundation function called &lt;code&gt;NSKVODeallocate&lt;/code&gt;.
&lt;br /&gt;6. Check out the annotated disassembly of that function from &lt;code&gt;otx&lt;/code&gt;. Notice that it invokes my &lt;code&gt;dealloc&lt;/code&gt; by fetching the &lt;code&gt;IMP&lt;/code&gt; using &lt;code&gt;class_getInstanceMethod&lt;/code&gt;. Immediately before that call is a call to &lt;code&gt;object_getIndexedIvars&lt;/code&gt;.
&lt;br /&gt;7. Put a breakpoint on &lt;code&gt;object_getIndexedIvars&lt;/code&gt; with the program stopped just before destroying &lt;code&gt;target&lt;/code&gt;. Run, hit the breakpoint. Print the argument to &lt;code&gt;object_getIndexedIvars&lt;/code&gt;, and find that it's the KVO subclass.
&lt;br /&gt;8. Guessing, I print &lt;code&gt;*(id *)object_getIndexedIvars(KVO subclass)&lt;/code&gt; and discover that it's &lt;code&gt;KVOTarget&lt;/code&gt;.
&lt;br /&gt;9. Write code to overwrite that with the intermediary class, run it, tests all pass, decide it's good.</description><guid isPermaLink="true">7c43d155120befa2487b03fe3aa398ab</guid><pubDate>Wed, 16 Mar 2011 17:48:20 GMT</pubDate></item><item><title>Chase - 2011-03-16 17:00:04</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>No problem, thanks for the fix! If you don't mind me asking, how did you come up with the fix for the crash I reported? I kind of figured it was being caused by KVO not respecting the runtime class hierarchy, but after that I had no idea where to proceed in trying to fix it.</description><guid isPermaLink="true">dfae583cc7af793110a28087460f7adc</guid><pubDate>Wed, 16 Mar 2011 17:00:04 GMT</pubDate></item><item><title>mikeash - 2011-03-16 15:05:04</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thanks a lot for that. I've fixed it. Your "NoCrash" test also revealed another KVO-related bug due to an ordering dependency in when subclasses are created. I assume you didn't encounter it because you ran your tests in a different order from mine. Fixes for both are now up on github.</description><guid isPermaLink="true">33d7d19f5b46c5049ab89dc33537ff36</guid><pubDate>Wed, 16 Mar 2011 15:05:04 GMT</pubDate></item><item><title>Chase - 2011-03-16 02:31:32</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>I've found another problem with MAZeroingWeakReference and KVO, unfortunately. I've posted a gist with two tests, one which crashes, and another which passes. The crash occurs when a KVO object is released, and you subsequently try to use the target of the ref. If the KVO subclass was created first, the crash will occur when dereferencing _target. If the target is embedded in an MAZeroingWeakRef first, and then KVO observed, no crash occurs.
&lt;br /&gt;
&lt;br /&gt;The gist is available here: &lt;a href="https://gist.github.com/871905#file_ma_zeroing_weak_ref%20kvo%20crash%20test"&gt;https://gist.github.com/871905#file_ma_zeroing_weak_ref%20kvo%20crash%20test&lt;/a&gt;</description><guid isPermaLink="true">6d48a7744e9b977502e826919b9a7b45</guid><pubDate>Wed, 16 Mar 2011 02:31:32 GMT</pubDate></item><item><title>mikeash - 2011-01-07 16:27:10</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>One problem with that is that it won't work on classes which implement their own reference counting mechanism, which while not exactly common, is not entirely unheard of either. Inline reference counting can be a nice little performance boost for objects that get retained and released with high frequency.</description><guid isPermaLink="true">3ce5345aede1b77fc5cc709b45ca158f</guid><pubDate>Fri, 07 Jan 2011 16:27:10 GMT</pubDate></item><item><title>Andrew - 2011-01-07 05:44:47</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>What is everyone's opinion on this approach?
&lt;br /&gt;
&lt;br /&gt;At startup, store NSObject's -release IMP somewhere and set it to your own function.  In your function, check [self retainCount].  If retainCount is 1, then the object is doomed and will be deallocated upon calling NSObject's original IMP for -release.  </description><guid isPermaLink="true">e65385fd5ea43f0e84049f5b70cb6881</guid><pubDate>Fri, 07 Jan 2011 05:44:47 GMT</pubDate></item><item><title>mikeash - 2010-09-18 19:39:34</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thanks very much for the bug report. I've applied your recommended fix in the project on github:
&lt;br /&gt;
&lt;br /&gt;&lt;a href="http://github.com/mikeash/MAZeroingWeakRef"&gt;http://github.com/mikeash/MAZeroingWeakRef&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;Due to the difficulty of maintaining both repositories, I am &lt;i&gt;not&lt;/i&gt; currently maintaining the Subversion repository with fixes like this. If there's demand for it I'll get them synced up, but github seems to be a better place to keep this anyway.</description><guid isPermaLink="true">f49689cb1d816924410fc81adf566539</guid><pubDate>Sat, 18 Sep 2010 19:39:34 GMT</pubDate></item><item><title>Jason - 2010-09-18 18:58:37</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Mike,
&lt;br /&gt;
&lt;br /&gt;Again, thank you for this excellent pair of classes. It has come in handy in a number of situations.
&lt;br /&gt;
&lt;br /&gt;Recently I have discovered a bug in MAZeroingWeakProxy, however. The usual program flow appears to go through "forwardingTargetForSelector:". 
&lt;br /&gt;
&lt;br /&gt;However, if the weak target has been deallocated, this will return nil, so the message goes through "forwardInvocation:". This works correctly, except for delegate-style messages returning void. I had come across a bug whereby the internals of NSInvocation was crashing because that method's "returnLength" was zero, and NSInvocation's "setReturnValue:" was crashing because of it (it calls setArgument:atIndex: which then calls __NSI2, __NSI0, and crashes).
&lt;br /&gt;
&lt;br /&gt;Simply wrapping those three lines in an "if (returnLength &amp;gt; 0)" block avoids the crash.
&lt;br /&gt;</description><guid isPermaLink="true">d42c76eb2374bb360f0cc54c286845aa</guid><pubDate>Sat, 18 Sep 2010 18:58:37 GMT</pubDate></item><item><title>mikeash - 2010-08-16 23:19:22</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thinking about it more, I believe a better solution would be to swizzle out the KVO subclass's implementation of &lt;code&gt;- release&lt;/code&gt; and &lt;code&gt;-dealloc&lt;/code&gt; and basically have a separate override path for them. This would prevent the KVO subclass from doing anything bad in &lt;code&gt;release&lt;/code&gt; or &lt;code&gt;dealloc&lt;/code&gt;. However, I can't think of a specific example, and I believe this probably can't actually happen in practice.</description><guid isPermaLink="true">d1b31f12a3352cdf4bfb1db2de923253</guid><pubDate>Mon, 16 Aug 2010 23:19:22 GMT</pubDate></item><item><title>Shirui - 2010-08-16 23:03:25</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Yeah, that's what I did as well... Sigh... Looking for a better (more fool-proof) solution though...</description><guid isPermaLink="true">75ef2b4870080e177b46fbf87cc2cd80</guid><pubDate>Mon, 16 Aug 2010 23:03:25 GMT</pubDate></item><item><title>mikeash - 2010-08-16 22:15:47</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>And fixed. I solved it by inserting the ZWR subclass &lt;i&gt;above&lt;/i&gt; the KVO subclass. This is horrible, but it does the job.
&lt;br /&gt;
&lt;br /&gt;The fix is up on github, but not yet in Subversion, as I have run into trouble getting them to communicate now.</description><guid isPermaLink="true">7323d01d2848448e3d74c0ae407f7800</guid><pubDate>Mon, 16 Aug 2010 22:15:47 GMT</pubDate></item><item><title>Shirui - 2010-08-16 21:50:05</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Well, I was easily able to reproduce the problem like this:
&lt;br /&gt;
&lt;br /&gt;1. Create a new Xcode project. (The App Delegate should be automatically generated for you.)
&lt;br /&gt;2. Open up the default XIB file and add an NSTextField to it, bound to some property of the App Delegate.
&lt;br /&gt;3. Declare the appropriate property in the App Delegate so that the binding works.
&lt;br /&gt;4. In -applicationDidFinishLaunching:, query object_getClass(self) and ensure that it's the NSKVONotifying version. Then, do the custom subclassing and query the object, i.e., [self description] and [self class] to see that you get junk values.
&lt;br /&gt;
&lt;br /&gt;Unfortunately, KVO is such a common case (bindings!) that I at least won't be able to use Weak Referencing until we can make it be friends with KVO. :-/</description><guid isPermaLink="true">bc9cc9b863499fdf26dd7ba49db878ec</guid><pubDate>Mon, 16 Aug 2010 21:50:05 GMT</pubDate></item><item><title>mikeash - 2010-08-16 21:21:45</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>I have now reproduced the problem, or at least &lt;i&gt;a&lt;/i&gt; problem. It doesn't manifest until you actually call an observed setter, or at least it didn't for me. It appears that the problem lies in KVO assuming that &lt;code&gt;self-&amp;gt;isa&lt;/code&gt; is the KVO class, and calling &lt;code&gt;object_getIndexedIvars&lt;/code&gt; on it. I'm investigating to see if this problem can somehow be mitigated in the general case. Overriding &lt;code&gt;automaticallyNotifiesObserversForKey:&lt;/code&gt; to always return &lt;code&gt;NO&lt;/code&gt; and doing manual notification should be a decent workaround though.
&lt;br /&gt;</description><guid isPermaLink="true">7b9a86976a13c4bc23573cb7cd0d9c28</guid><pubDate>Mon, 16 Aug 2010 21:21:45 GMT</pubDate></item><item><title>mikeash - 2010-08-16 20:06:27</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>That is really odd. I was afraid of KVO subclasses getting screwed up, but a quick test doesn't show any problems. The only way I can possibly see that your class could end up as &lt;code&gt;0x0&lt;/code&gt; after &lt;code&gt;object_setClass&lt;/code&gt; is if you're passing &lt;code&gt;nil&lt;/code&gt; to that function to begin with.
&lt;br /&gt;
&lt;br /&gt;Would it be possible for you to produce a small test case that shows the problem? My KVO test case is up on my svn and github if you want to compare with it.</description><guid isPermaLink="true">5ec187c124ccb9342d2daf76245ebc7b</guid><pubDate>Mon, 16 Aug 2010 20:06:27 GMT</pubDate></item><item><title>Shirui - 2010-08-16 05:38:09</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Hmm... you might be right. I've yet to actually check whether retainCount indeed returns 0 when the object is in -dealloc.
&lt;br /&gt;
&lt;br /&gt;In the meanwhile though, I've found a more concerning issue. It looks like the custom subclasses that KVO makes do not like to be subclassed. I was seeing some random crashes in CFEqual recently and traced the problem down to the fact that one of my object's class information was getting corrupted when its class was changed to be a weak reference.
&lt;br /&gt;
&lt;br /&gt;Here's briefly what I got in the debugger:
&lt;br /&gt;
&lt;br /&gt;BEFORE object_setClass is called:
&lt;br /&gt;&amp;gt; po [object class]
&lt;br /&gt;AppDelegate
&lt;br /&gt;&amp;gt; po currClass
&lt;br /&gt;NSKVONotifying_AppDelegate
&lt;br /&gt;&amp;gt; po customSubclass
&lt;br /&gt;NSKVONotifying_AppDelegate_WeakReferenceable
&lt;br /&gt;
&lt;br /&gt;And just AFTER object_setClass is called:
&lt;br /&gt;&amp;gt; po [object class]
&lt;br /&gt;0x0
&lt;br /&gt;&amp;gt; po object
&lt;br /&gt;&amp;lt;not an object or object does not respond to description method&amp;gt;
&lt;br /&gt;
&lt;br /&gt;This is very disturbing and I'm not sure exactly what's going wrong. Have you seen anything like this? Any ideas?</description><guid isPermaLink="true">7d957848d1a5884b34b246c0d1db844d</guid><pubDate>Mon, 16 Aug 2010 05:38:09 GMT</pubDate></item><item><title>mikeash - 2010-08-13 02:41:23</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>You can't really check for retainCount &amp;gt; 0, because that never happens. Cocoa reference counting is optimized to not store an entry for objects with a retain count of 1, so any object without a retain count entry is assumed to have a count of 1. When you release an object with a count of 1, it is destroyed, but it never gets an entry to say that its count is 0, because, well, it's being destroyed.
&lt;br /&gt;
&lt;br /&gt;I suppose I could maintain a collection of weak refs that are in the middle of destruction and assert that nobody tries to resurrect them, but I think that with the two-stage zeroing/cleanup process, it's not really needed.</description><guid isPermaLink="true">6f9d19d0dfe4307610758ce5c74154e4</guid><pubDate>Fri, 13 Aug 2010 02:41:23 GMT</pubDate></item><item><title>Shirui - 2010-08-13 00:26:10</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>It eventually comes down to the same thing as "resurrection" in the GC world, wherein if you have snuck away a pointer to object A somewhere, you can try to make a new weak pointer to it during A's dealloc, inside your cleanup block. There are no clear safeguards against it, but at the least you can add a check for retainCount &amp;gt; 0, before you agree to make a weak ref out of an object.</description><guid isPermaLink="true">00c0ba1999a297a0e3565b01cbdad408</guid><pubDate>Fri, 13 Aug 2010 00:26:10 GMT</pubDate></item><item><title>mikeash - 2010-08-12 20:55:30</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>After more thought, I decided that splitting weak ref cleanup into two stages makes a lot of sense. It makes it much easier to write safe cleanup blocks and eliminates the potential for some ugly bugs. I've gone ahead and made that change and committed it.</description><guid isPermaLink="true">5211a179f8fa06123c4c417a0aefa6dd</guid><pubDate>Thu, 12 Aug 2010 20:55:30 GMT</pubDate></item><item><title>mikeash - 2010-08-12 20:13:40</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>If you create a new weak reference to the target in your cleanup block, I would consider that to be a bug.
&lt;br /&gt;
&lt;br /&gt;However, in a program with complicated object graphs, it may not be easy to realize what you're doing. This is why you should keep your cleanup block minimal.
&lt;br /&gt;
&lt;br /&gt;I'm starting to think that zeroing the target and calling the cleanup block should happen in two passes. Pass one, zero all targets. Pass two, execute cleanup blocks for anything that needs it. That will ensure that you can't accidentally make new references to the target (or accidentally resurrect the target through an existing weak reference), as the &lt;code&gt;target&lt;/code&gt; parameter will be the only way you could possibly get to it.
&lt;br /&gt;
&lt;br /&gt;I'll have to think about this....</description><guid isPermaLink="true">7fa8692f9730ede2c1268b20ab1bf5a4</guid><pubDate>Thu, 12 Aug 2010 20:13:40 GMT</pubDate></item><item><title>Shirui - 2010-08-12 18:34:21</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Hmm, OK, another edge case: in ClearWeakRefsForObject, you make a copy of the set to ensure that you are not iterating over a set that's being mutated. Now, what if, as part of the cleanup block, someone goes and creates a weak reference to the object for which ClearWeakRefsForObject is being called? It looks like the new value would get added to the set, but the set would get removed from the dictionary at the end of ClearWeakRefsForObject, leaving a dangling pointer behind in this brand new weak ref...
&lt;br /&gt;
&lt;br /&gt;Potential fixes: when you enter ClearWeakRefsForObject, poison the object that you are entering for and make sure no new refs get added for it.</description><guid isPermaLink="true">944ae80ac90cd62f570d5389f726bf80</guid><pubDate>Thu, 12 Aug 2010 18:34:21 GMT</pubDate></item><item><title>mikeash - 2010-08-11 04:45:45</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Right, I'm basically expanding the scope of what needs to be atomic, so I have to add my own mutex to the mix.
&lt;br /&gt;
&lt;br /&gt;If you are leaving out cleanup blocks then you won't need to duplicate the set, as without them, there is nothing that &lt;code&gt;_zeroTarget&lt;/code&gt; can do to cause the set to mutate.</description><guid isPermaLink="true">cda38cabb87188a044350723fcf7b762</guid><pubDate>Wed, 11 Aug 2010 04:45:45 GMT</pubDate></item><item><title>Shirui - 2010-08-10 21:04:41</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thanks for the clarification! I was referring to the mutex around the call to -retain in -target, but I see why that's necessary now. I also understand your argument about -release and -retain being thread-safe on their own, but the fact that you want to make sure the operation of "release and nil out references if necessary" is atomic as a whole. Am I right?
&lt;br /&gt;
&lt;br /&gt;Also, I'm guessing (correctly, I hope) that I don't need to duplicate the set for my implementation because I am not using a cleanup block and so it should not be the case that something is enumerating over the set while the another thing is mutating it.</description><guid isPermaLink="true">42ca0d9c2ebdac405f1cc785f6aed3f6</guid><pubDate>Tue, 10 Aug 2010 21:04:41 GMT</pubDate></item><item><title>mikeash - 2010-08-10 19:06:58</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>The mutex around the &lt;code&gt;release&lt;/code&gt; (I don't think there's one around &lt;code&gt;retain&lt;/code&gt;) is to prevent a race condition that would appear otherwise. Imagine this scenario: thread A releases the last strong reference. Thread B uses a weak reference. Thread A destroys the object. Thread B accesses the destroyed object, crashing.
&lt;br /&gt;
&lt;br /&gt;The mutex prevents this from happening. Essentially, Apple's code is thread safe but the code I add on to it is not unless I add a mutex to it as well. Thread safety is often tricky like that: X can be thread safe, and Y can be thread safe, but the combination of X+Y may not necessarily be thread safe without taking additional action.
&lt;br /&gt;
&lt;br /&gt;As for copying the set, it is possible for a cleanup block to mutate the set of weak references on the object, which then causes an enumeration mutation exception. (It is forbidden to mutate a collection while enumerating over it in Cocoa.) Thus I make a copy of the set to ensure that it doesn't get mutated during enumeration. See &lt;code&gt; TestCleanupBlockReleasingZWR&lt;/code&gt; in &lt;code&gt;main.m&lt;/code&gt; for an example of how that could happen.</description><guid isPermaLink="true">2f1e0a3f3e106369afb9d9be20a17961</guid><pubDate>Tue, 10 Aug 2010 19:06:58 GMT</pubDate></item><item><title>Shirui - 2010-08-10 18:20:24</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Just read through the entry and all the comments. Brilliant work! Thank you!
&lt;br /&gt;
&lt;br /&gt;A couple of questions though:
&lt;br /&gt;
&lt;br /&gt;1. According to the thread-safety summary on Apple's Developer site (&lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-SW1"&gt;http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-SW1&lt;/a&gt;), "Object allocation and retain count functions" and "Zone and memory functions" are thread-safe. Why then do we need a mutex around the call to release and retain?
&lt;br /&gt;
&lt;br /&gt;2. In ClearWeakRefsForObject, why make a copy of the set instead of taking a mutex around it like everywhere else?
&lt;br /&gt;
&lt;br /&gt;Thanks!</description><guid isPermaLink="true">37cc7476ae625d51f36bca47f3945b5b</guid><pubDate>Tue, 10 Aug 2010 18:20:24 GMT</pubDate></item><item><title>mikeash - 2010-07-23 01:08:44</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>I've now fixed the code to build without blocks, by making WhileLocked a macro. I've also fixed the problem found by Steve Brambilla which could cause a mutation exception while zeroing out targets. These changes are in my repository.
&lt;br /&gt;
&lt;br /&gt;Thanks very much to both of you for finding these problems, and Jason, it's very neat to hear how you've used this stuff to solve your problem.</description><guid isPermaLink="true">71b9ad2c50affa049739449f83de1115</guid><pubDate>Fri, 23 Jul 2010 01:08:44 GMT</pubDate></item><item><title>mikeash - 2010-07-23 00:21:50</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Duh, I forgot that &lt;code&gt;WhileLocked&lt;/code&gt; would cause problems on blockless OSes. I should probably macroize it so it can work on older systems.</description><guid isPermaLink="true">1b097c4a9a53a5f68bcc4cf076109306</guid><pubDate>Fri, 23 Jul 2010 00:21:50 GMT</pubDate></item><item><title>Jason - 2010-07-22 22:43:23</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thanks again for this. Fully integrated it, and it works beautifully. The proxy is deallocated with the UIWebView, and the zeroing ref's target was nil as intended.
&lt;br /&gt;
&lt;br /&gt;The only catch was that I had to "insert" the contents WhileLocked, since I am targeting blockless iOS 3.2.
&lt;br /&gt;</description><guid isPermaLink="true">10fd46ba73a578fa0c826f24d688c2fd</guid><pubDate>Thu, 22 Jul 2010 22:43:23 GMT</pubDate></item><item><title>mikeash - 2010-07-20 01:13:22</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>That's why the check is different (better, as far as I know 100% reliable) if &lt;code&gt;COREFOUNDATION_HACK_LEVEL&lt;/code&gt; is set to 1 or 2.
&lt;br /&gt;
&lt;br /&gt;If you or anyone else should happen to know of a better way to check for TFBness without using private CF API or doing a lame check for an NSCF prefix, I'd be very interested to know. I was not able to find any such way when I built this, but that doesn't mean it's not possible.</description><guid isPermaLink="true">42e7c0768ebb367cae421ba77cae6e9b</guid><pubDate>Tue, 20 Jul 2010 01:13:22 GMT</pubDate></item><item><title>Ned Holbrook - 2010-07-19 18:10:00</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>On the toll-free bridging front, I would note that there are bridged classes that your check won't catch: NSFont/CTFont{Descriptor} comes to mind.</description><guid isPermaLink="true">6dbf7a55166ec4951e5470d50b0e244f</guid><pubDate>Mon, 19 Jul 2010 18:10:00 GMT</pubDate></item><item><title>mikeash - 2010-07-19 11:20:36</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>The original set is specially constructed not to retain its contents, and the copy probably keeps that attribute. You could fix it by replacing the copy with &lt;code&gt;[[NSSet alloc] initWithSet: (NSSet *)set]&lt;/code&gt;. Then you wouldn't have to manually retain/release the contents.</description><guid isPermaLink="true">c303996397d8b2d96bfc17c264928fb7</guid><pubDate>Mon, 19 Jul 2010 11:20:36 GMT</pubDate></item><item><title>Steve Brambilla - 2010-07-19 02:57:50</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Replacing it with this code works:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;static void ClearWeakRefsForObject(id obj)
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CFMutableSetRef set = (void *)CFDictionaryGetValue(gObjectWeakRefsMap, obj);
&lt;br /&gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NSSet *setCopy = [(NSSet *)set copy];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[setCopy makeObjectsPerformSelector: @selector(retain)];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[setCopy makeObjectsPerformSelector: @selector(_zeroTarget)];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[setCopy makeObjectsPerformSelector: @selector(release)];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[setCopy release];
&lt;br /&gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CFDictionaryRemoveValue(gObjectWeakRefsMap, obj);
&lt;br /&gt;}
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Without the extra retain / release messages the objects can be deallocated while it's enumerating sending &lt;code&gt;_zeroTarget&lt;/code&gt;. But I don't completely understand why; shouldn't &lt;code&gt;setCopy&lt;/code&gt; already retain them? 
&lt;br /&gt;Sending the extra retain / release messages feels sloppy...</description><guid isPermaLink="true">e6236ca76a37023cb40ec172ba9a7593</guid><pubDate>Mon, 19 Jul 2010 02:57:50 GMT</pubDate></item><item><title>mikeash - 2010-07-19 01:12:19</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Nice catch. I think the answer is to enumerate over a copy of the set rather than the original. That will hurt performance slightly, but will allow cleanup code to mutate the set. I don't have time to make the modification right now, but it should be a simple matter of sticking a copy and release in the method in question. I will get to it at some point....</description><guid isPermaLink="true">b0f7b85db9655c253dff9abe9f837c82</guid><pubDate>Mon, 19 Jul 2010 01:12:19 GMT</pubDate></item><item><title>Steve Brambilla - 2010-07-18 23:16:54</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>I figured it may have been used for something like that.
&lt;br /&gt;
&lt;br /&gt;The other thing that I've observed is a rare set mutation while enumerating exception in &lt;code&gt;ClearWeakRefsForObject&lt;/code&gt;. This is what I think is happening: it occurs if the cleanup block releases another instance of &lt;code&gt;MAZeroingWeakRef&lt;/code&gt; that has its target set to the object being deallocated. When the &lt;code&gt;MAZeroingWeakRef&lt;/code&gt; is deallocated &lt;code&gt;RemoveWeakRefFromObject&lt;/code&gt; gets called, which mutates the set that is still being enumerated by &lt;code&gt;makeObjectsPerformSelector:&lt;/code&gt;.
&lt;br /&gt;
&lt;br /&gt;I observed this when I added another weak observer method to &lt;code&gt;NSNotificationCenter&lt;/code&gt; to support blocks:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;- (void)addWeakObserver:(id)observer forName:(NSString *)name object:(NSString *)object onQueue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *))block
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;id observerToken = [self addObserverForName:name object:object queue:queue usingBlock:block];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MAZeroingWeakRef *ref = [[MAZeroingWeakRef alloc] initWithTarget:observer];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[ref setCleanupBlock: ^(id target) {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[self removeObserver:observerToken];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[ref autorelease];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}];
&lt;br /&gt;}
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;And then used it something like this:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;MAZeroingWeakRef *selfRef = [MAZeroingWeakRef refWithTarget:self];
&lt;br /&gt;[[NSNotificationCenter defaultCenter] addWeakObserver:self forName:MyNotification object:nil onQueue:nil usingBlock:^(NSNotification *note) {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[[selfRef target] doWhatever];
&lt;br /&gt;}];
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;When &lt;code&gt;NSNotificationCenter&lt;/code&gt; releases the block, the captured &lt;code&gt;MAZeroingWeakRef&lt;/code&gt; gets deallocated while it's target is clearing its weak references.
&lt;br /&gt;
&lt;br /&gt;I'm not sure the best way to handle a mutating set, but I presume that if the set could be enumerated while being mutated that it would solve this, or would there be some other side effect I've overlooked?</description><guid isPermaLink="true">5b8da08e583d76e20f136c23a3225bda</guid><pubDate>Sun, 18 Jul 2010 23:16:54 GMT</pubDate></item><item><title>mikeash - 2010-07-18 19:47:42</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Good catch. That's just a leftover from my earlier experiments with CF workarounds. (I was having some trouble and thought that CF might need to be poked to initialize some values.) I've removed it from the repository.</description><guid isPermaLink="true">d5ef59801e5dcfb4c11323767c033332</guid><pubDate>Sun, 18 Jul 2010 19:47:42 GMT</pubDate></item><item><title>Steve Brambilla - 2010-07-18 19:28:14</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thanks a lot for this, I have already found it very useful over the past couple days.
&lt;br /&gt;
&lt;br /&gt;In &lt;code&gt;+ initialize&lt;/code&gt; the line &lt;code&gt;CFStringCreateMutable(NULL, 0);&lt;/code&gt; creates a mutable string that is never referenced or used. Can we safely remove this, or is it somehow part of the hackery?</description><guid isPermaLink="true">31c8208e2da05ee8230818d070bc9f4e</guid><pubDate>Sun, 18 Jul 2010 19:28:14 GMT</pubDate></item><item><title>Jason - 2010-07-17 20:30:11</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>The docs say:
&lt;br /&gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;The UIWebView class should not be subclassed.
&lt;br /&gt;
&lt;br /&gt;So I'll stick with objc_setAssociatedObject and implement some category methods on UIWebView. Thanks again!
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">b47df5a9c6cc681ff59aba8db46b5c8c</guid><pubDate>Sat, 17 Jul 2010 20:30:11 GMT</pubDate></item><item><title>mikeash - 2010-07-17 18:51:26</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>If your OS requirement is iOS 3.1+, then you can use &lt;code&gt;objc_setAssociatedObject&lt;/code&gt; to associate the proxy with the web view. Then it won't get deallocated until the web view does.
&lt;br /&gt;
&lt;br /&gt;Another possibility: can you subclass &lt;code&gt;UIWebView&lt;/code&gt;? If so, you could add the proxy as an instance variable, and release it in &lt;code&gt;dealloc&lt;/code&gt;.</description><guid isPermaLink="true">5ad1bc2bdc9eaa9034023b13838e44d3</guid><pubDate>Sat, 17 Jul 2010 18:51:26 GMT</pubDate></item><item><title>Jason - 2010-07-17 18:26:19</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>On looking at the source, it appears to be exactly what is called for. However, I fear that it may wind up having to leak the proxy in order to resolve the crash issue. The great thing is that it allows the real target to be released (of course), but to keep UIWebView from crashing I expect that I will need to keep the proxy object alive.
&lt;br /&gt;
&lt;br /&gt;I can probably avoid a crash by releasing it after some time. I'd like to do something like this in my FooController:
&lt;br /&gt;
&lt;br /&gt;// setup
&lt;br /&gt;webView = ...;
&lt;br /&gt;myProxy = [[MAZeroingWeakProxy alloc] initWithTarget:self];
&lt;br /&gt;webView.delegate = myProxy;
&lt;br /&gt;
&lt;br /&gt;// dealloc
&lt;br /&gt;if (myProxy)
&lt;br /&gt;{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[myProxy performSelector:@selector(description) withObject:nil afterDelay:60];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[myProxy release];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Now, only NSObject has a strong reference.
&lt;br /&gt;}
&lt;br /&gt;webView.delegate = nil;
&lt;br /&gt;
&lt;br /&gt;But of course, NSProxy doesn't support that method. I'd have to set up a non-repeating NSTimer, I think. Not the best, but I think it's the only way. 
&lt;br /&gt;</description><guid isPermaLink="true">058ffd8349a2b74bb37d475e0e148534</guid><pubDate>Sat, 17 Jul 2010 18:26:19 GMT</pubDate></item><item><title>mikeash - 2010-07-17 18:08:36</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Sure, and I'd be very interested in hearing how it works out for you.</description><guid isPermaLink="true">a09a333ade21a4c7490b39c3b8e2ad62</guid><pubDate>Sat, 17 Jul 2010 18:08:36 GMT</pubDate></item><item><title>Jason - 2010-07-17 18:01:02</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Thanks so much!</description><guid isPermaLink="true">e296c9c04e199ac7f713f7266393fa86</guid><pubDate>Sat, 17 Jul 2010 18:01:02 GMT</pubDate></item><item><title>mikeash - 2010-07-17 16:06:27</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>With all the talk about proxies, I went ahead and implemented one. &lt;code&gt;MAZeroingWeakProxy&lt;/code&gt; is available in the subversion repository now. I still recommend using the explicit weak ref wherever it makes sense, but for things like faking out delegates for framework objects, the proxy is probably a better choice.</description><guid isPermaLink="true">116467c782cdcf76b42b27da39abf66a</guid><pubDate>Sat, 17 Jul 2010 16:06:27 GMT</pubDate></item><item><title>mikeash - 2010-07-17 15:11:08</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>That is nasty. An &lt;code&gt;NSProxy&lt;/code&gt; subclass which bounces messages through a &lt;code&gt;MAZeroingWeakRef&lt;/code&gt; should solve your problem, and is probably a nicer way to approach delegates/data sources for code you don't own in general. Attach the proxy to the &lt;code&gt;UIWebView&lt;/code&gt; as an associated object (if you can require an OS version that has them) and you won't have to worry about memory management.</description><guid isPermaLink="true">ad6237c1bf0d81cc2b0bd8316d80dbff</guid><pubDate>Sat, 17 Jul 2010 15:11:08 GMT</pubDate></item><item><title>Jason - 2010-07-17 14:51:58</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>This is incredibly useful. We are having to implement a related utility class that solves this problem from another perspective -- when we aren't the ones calling into the delegate. Specifically, we have found that UIWebViews continue to send messages to their delegate even after setting their delegate to nil on the main thread. 
&lt;br /&gt;
&lt;br /&gt;It appears that because of JavaScript running on a timer, or something to that effect, there are cases whereby an Invocation has been queued up to send from a background web thread while the main thread is busy unsetting the UIWebView's delegate (because that object is being dealloc'ed). By the time the invocation makes it to the main thread, it attempts to send a message to the deallocated object.
&lt;br /&gt;
&lt;br /&gt;Attempting to solve it through another proxy-like object like this one.
&lt;br /&gt;</description><guid isPermaLink="true">410977f0a9850455529fc036195e5a8c</guid><pubDate>Sat, 17 Jul 2010 14:51:58 GMT</pubDate></item><item><title>mikeash - 2010-07-17 13:50:58</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Regarding the proxy idea, I thought about it, but decided against it because it's too easy to forget that your target can disappear in the middle of your code if you use a proxy. For example:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;if([weakRef condition]) // alive here
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[weakRef doSomethingImportantWithObject: self]; // gone here
&lt;br /&gt;else
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[self doSomethingEquallyImportant]; // never gets here
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Whereas with an explicit reference, you have to work very hard to create that problem. Normally you'd write:
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;id obj = [weakRef target]; // obj is now in autorelease pool, stays alive through the end of the code
&lt;br /&gt;if([obj condition]
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[obj doSomethingImportantWithObject: self];
&lt;br /&gt;else
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[self doSomethingEquallyImportant];
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;And you don't have to structure your code to tolerate having the object disappear in mid-stream.
&lt;br /&gt;
&lt;br /&gt;As for the cleanup block, referring to &lt;code&gt;target&lt;/code&gt; there is no more dangerous (and actually slightly safer) than referring to &lt;code&gt;self&lt;/code&gt; in &lt;code&gt;dealloc&lt;/code&gt;, which we do all the time. The notification example is semantically the same as the extremely common pattern of removing a notification observer in &lt;code&gt;dealloc&lt;/code&gt;.</description><guid isPermaLink="true">5b64bd1ff1e0ef206681d3167f2bcaf8</guid><pubDate>Sat, 17 Jul 2010 13:50:58 GMT</pubDate></item><item><title>Ken Thomases - 2010-07-17 11:16:22</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Oh, and don't you have to be extraordinarily careful in the cleanup block?  Almost any reference to the target is dangerous.
&lt;br /&gt;
&lt;br /&gt;First, there's the problem of resurrecting the object.  This is especially likely if you reference the target in a deferred way, like you suggest.
&lt;br /&gt;
&lt;br /&gt;Second, there's the problem that the target is partially dealloc'd already, in the case that KVO (or something else) has subclassed after MAZeroingWeakRef.
&lt;br /&gt;
&lt;br /&gt;It's not clear to me that even your NSNotificationCenter(MAZeroingWeakRefAdditions) category is safe.
&lt;br /&gt;
&lt;br /&gt;I almost think that you shouldn't support passing the target to the cleanup block.  Or perhaps it would be passed as a uintptr_t so it can't accidentally be used as an actual object pointer.</description><guid isPermaLink="true">2e737b23aca12e9878387b0c18e8b901</guid><pubDate>Sat, 17 Jul 2010 11:16:22 GMT</pubDate></item><item><title>Ken Thomases - 2010-07-17 10:51:59</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Have you considered making MAZeroingWeakRef a proxy for its target?</description><guid isPermaLink="true">e76e1263e4ae898bc6b0cea0e6ecfbe6</guid><pubDate>Sat, 17 Jul 2010 10:51:59 GMT</pubDate></item><item><title>mikeash - 2010-07-17 02:16:17</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>I want to mention further: I don't think that non-thread-safe zeroing weak references are useful in any general sense. They may work for specific situations, but it's far too easy to lose control of your object's lifetime and end up having it be deallocated on another thread without meaning to. Just capture an object in a block and pass it to GCD and you're toast.
&lt;br /&gt;
&lt;br /&gt;Such zeroing weak references are easy to construct, and have been done before. What &lt;code&gt;MAZeroingWeakRef&lt;/code&gt; brings to the table is that it is, as far as I know, the first such implementation that is thread safe, and therefore safe to use in the general case.</description><guid isPermaLink="true">ebd73a92ad0dd905973519b4b81b3834</guid><pubDate>Sat, 17 Jul 2010 02:16:17 GMT</pubDate></item><item><title>mikeash - 2010-07-17 02:00:35</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>Associated objects make zeroing weak references really easy if you don't care about thread safety. Unfortunately they're completely useless for thread-safe zeroing weak references.
&lt;br /&gt;
&lt;br /&gt;The reason is object resurrection. You have to zero out all weak references to an object &lt;i&gt;before&lt;/i&gt; that object's dealloc (or CF finalize function) executes, &lt;i&gt;and&lt;/i&gt; any queries to a weak reference which return an object &lt;i&gt;must&lt;/i&gt; prevent dealloc or finalize from executing at all.
&lt;br /&gt;
&lt;br /&gt;By the time an associated object is freed, it's far too late to prevent the object it's associated with from being destroyed, so you end up with horrible race conditions.
&lt;br /&gt;
&lt;br /&gt;This is why the pure ObjC override hits both release and dealloc; simply overriding dealloc isn't enough, as you end up with a race condition between the final call to release and the call to dealloc.
&lt;br /&gt;
&lt;br /&gt;The CF craziness gets around it because pure CF objects are allowed to resurrect themselves in their finalize function, thus I override that and check for the condition where a weak reference has caused resurrection before proceeding with object destruction.</description><guid isPermaLink="true">591aa8529c09470aaaf87300d6fa884b</guid><pubDate>Sat, 17 Jul 2010 02:00:35 GMT</pubDate></item><item><title>Clark Cox - 2010-07-17 00:21:32</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html#comments</link><description>I wonder if you've considered using objc_setAssociatedObject instead of class/method swizzling. That is, associate an object with the target object that, itself, gets released when the target object is deallocated. This may allow you to work with CF objects without needing any kind of hack or private-API calls</description><guid isPermaLink="true">5ed112e0ddb695f8ee98ca2d87c1c2a6</guid><pubDate>Sat, 17 Jul 2010 00:21:32 GMT</pubDate></item></channel></rss>
