<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>mikeash.com pyblog/friday-qa-2009-01-23.html comments</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>mikeash.com Recent Comments</description><lastBuildDate>Fri, 07 Aug 2026 11:42:12 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Prashant - 2018-10-23 10:07:48</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Thanks a lot for sharing the internals of KVO!!
&lt;br /&gt;I have a though on an alternate approach and would like to now if that would be achievable.
&lt;br /&gt;KVO could also be implemented by swapping the original setter with a custom setter that calls the observers with the new value and then calls the original setter. Would that also be a possibility to implement this feature?</description><guid isPermaLink="true">8c4cff3a625f8e0061389397749ca94e</guid><pubDate>Tue, 23 Oct 2018 10:07:48 GMT</pubDate></item><item><title>Wilson - 2018-07-03 13:15:23</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>I am a new bee in Objective-C and really appreciated to your article, it given me a lot of help. I already knew how to use nm -a command to kvoexplorer.o file. But I have no idea to how to use nm -a to Foundation. Thanks!</description><guid isPermaLink="true">7eb47e7e72453201d9fe94e2fc1446e5</guid><pubDate>Tue, 03 Jul 2018 13:15:23 GMT</pubDate></item><item><title>Jonathan Mitchell - 2017-05-31 10:34:39</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Some dogs don't know when to get old and die.
&lt;br /&gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Note that when observing deep keypaths such as obs observes xy.brain.structure.name the registered observer for structure (0x100600600) is not the original observer (obs) but a NSKeyValueObservance instance associated with obs.
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;obs : 0x100400170
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;obs.xy : 0x100400d10
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;obs.xy : &amp;lt;NSKeyValueObservationInfo 0x100500ca0&amp;gt; (
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;NSKeyValueObservance 0x1003041e0: Observer: 0x100400170, Key path: x, Options: &amp;lt;New: NO, Old: NO, Prior: NO&amp;gt; Context: 0x0, Property: 0x1004012c0&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;NSKeyValueObservance 0x100306320: Observer: 0x100400170, Key path: y, Options: &amp;lt;New: NO, Old: NO, Prior: NO&amp;gt; Context: 0x0, Property: 0x100306350&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;NSKeyValueObservance 0x100401140: Observer: 0x100400170, Key path: brain.name, Options: &amp;lt;New: YES, Old: YES, Prior: NO&amp;gt; Context: 0x0, Property: 0x100401890&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;NSKeyValueObservance 0x100600000: Observer: 0x100400170, Key path: brain.structure.name, Options: &amp;lt;New: YES, Old: YES, Prior: NO&amp;gt; Context: 0x0, Property: 0x1004041e0&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;obs.xy.brain : &amp;lt;NSKeyValueObservationInfo 0x103800370&amp;gt; (
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;NSKeyValueObservance 0x100600600: Observer: 0x100600000, Key path: structure.name, Options: &amp;lt;New: YES, Old: YES, Prior: NO&amp;gt; Context: 0x0, Property: 0x100500dd0&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;NSKeyValueObservance 0x103800340: Observer: 0x100401140, Key path: name, Options: &amp;lt;New: YES, Old: YES, Prior: NO&amp;gt; Context: 0x0, Property: 0x100402d20&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;obs.xy.brain.structure : &amp;lt;NSKeyValueObservationInfo 0x100600690&amp;gt; (
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;NSKeyValueObservance 0x100600660: Observer: 0x100600600, Key path: name, Options: &amp;lt;New: YES, Old: YES, Prior: NO&amp;gt; Context: 0x0, Property: 0x1005011f0&amp;gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&lt;br /&gt;&lt;/code&gt;</description><guid isPermaLink="true">4cd920061cc411b2db6e986c7a4616ad</guid><pubDate>Wed, 31 May 2017 10:34:39 GMT</pubDate></item><item><title>Parsifal - 2017-05-04 05:37:56</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Thanks for your post.It helped me a lot to dig deeper into KVO, although it's written 8 years ago.But I found a typo from your comment which replied to Ashley Clark about custom structs.As you said, apple do some forwarding stuff for those custom structs.But it's forwarded by -forwardingTargetForSelector not -forwardInvocation.That's different.</description><guid isPermaLink="true">119e39ff5fb65052f0ff5e2c56688b26</guid><pubDate>Thu, 04 May 2017 05:37:56 GMT</pubDate></item><item><title>Alex Nazaroff - 2016-02-19 09:37:17</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>I found what Xcode is tricky cheater. When I'm creating subclass with prefix &lt;code&gt;"NSKVONotifying_"&lt;/code&gt; and override class method - it looks like you described and only runtime tells us what it's the our lying class. 
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;But&lt;/b&gt; when I name prefix with another string, for example &lt;code&gt;"NSKVONotifyingA_"&lt;/code&gt;, Xcode shows in debugger real name &lt;code&gt;"NSKVONotifyingA_TestObject"&lt;/code&gt;. However &lt;code&gt;myObj.class&lt;/code&gt; returns his superclass &lt;code&gt;"TestObject"&lt;/code&gt;, as expected. I tried create classes in code, at runtime, etc – but result is the same – Xcode shows real class name. Looks like they use object_getClass call and have exception for KVO prefix.</description><guid isPermaLink="true">cdc8b7f453fba78347bd2538ad49e8a5</guid><pubDate>Fri, 19 Feb 2016 09:37:17 GMT</pubDate></item><item><title>mikeash - 2015-06-22 15:06:10</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Without actually testing to find out, I think that whether &lt;code&gt;methodForSelector:&lt;/code&gt; works depends on when you call it. If you call it on an object that has already had its class swizzled, you'll get the KVO-aware shim setter and all will be well. If you call it on a virgin object, you'll get the naive setter that doesn't invoke KVO. I don't think this would have changed.</description><guid isPermaLink="true">3d62f23ce3309143c5c8c415830f95b9</guid><pubDate>Mon, 22 Jun 2015 15:06:10 GMT</pubDate></item><item><title>Árpád Goretity "H2CO3" - 2015-06-22 06:24:26</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Sorry for the late revival of this old article, but here's my observation (no pun intended): so basically, if back in 2009 you used &lt;code&gt;-[NSObject methodForSelector:]&lt;/code&gt; for obtaining a setter method, then &lt;b&gt;calls to that setter wouldn't have shown up in KVO?&lt;/b&gt;
&lt;br /&gt;
&lt;br /&gt;It seems to me that it is indeed the case, but unfortunately I can't reproduce it (&lt;code&gt;methodForSelector:&lt;/code&gt; now returns the modified setter…)
&lt;br /&gt;</description><guid isPermaLink="true">5339f2b9afe7c5c6f7aafa14b674fb8a</guid><pubDate>Mon, 22 Jun 2015 06:24:26 GMT</pubDate></item><item><title>mikeash - 2011-09-14 15:14:07</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>That's called "when entities attack". Fixed now, thanks.</description><guid isPermaLink="true">56a25c2dc58c56e5be9bd224b5e64cf2</guid><pubDate>Wed, 14 Sep 2011 15:14:07 GMT</pubDate></item><item><title>Mike Johnson - 2011-09-12 18:34:08</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Thanks for the article! I know it's been around for a long while, but...
&lt;br /&gt;
&lt;br /&gt;Did you mean to have the ;); below, or do you have an extra semicolon?
&lt;br /&gt;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Method *methodList = class_copyMethodList(c, &amp;amp;methodCount;);
&lt;br /&gt;</description><guid isPermaLink="true">2659c7eba02c2725fa21ab5c8d4f446f</guid><pubDate>Mon, 12 Sep 2011 18:34:08 GMT</pubDate></item><item><title>Paulo Andrade - 2011-05-24 11:09:27</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Didn't know that. Having a per class table sounds better than a global table.
&lt;br /&gt;
&lt;br /&gt;I guess one would have to have access to the code to be sure on how it is really done. :)
&lt;br /&gt;
&lt;br /&gt;Terrific post nonetheless. </description><guid isPermaLink="true">38643870850e931e55cda3dd4a099ede</guid><pubDate>Tue, 24 May 2011 11:09:27 GMT</pubDate></item><item><title>mikeash - 2011-05-24 00:02:06</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>The language doesn't support class variables, but the runtime does. You can allocate storage for them with the &lt;code&gt;extraBytes&lt;/code&gt; parameter to &lt;code&gt;objc_allocateClassPair&lt;/code&gt;. I believe they can be accessed with &lt;code&gt;object_getIndexedIvars&lt;/code&gt;. KVO uses this for something, although I don't know what, as my only familiarity with it is watching it crash after pulling isa-swizzling shenanigans on KVO-occupied objects.</description><guid isPermaLink="true">c59eb5b094ec1fbf2a526a69d4131517</guid><pubDate>Tue, 24 May 2011 00:02:06 GMT</pubDate></item><item><title>Paulo Andrade - 2011-05-23 16:37:16</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>Yes, the global table could be how it's done. It just doesn't sound very elegant.
&lt;br /&gt;
&lt;br /&gt;As for the KVO subclass, how would it provide any storage? 
&lt;br /&gt;You are creating these classes dynamically, and there are no "class variables" in Objective-C. Even if there were, this would be a similar solution to the global table since these dynamic subclasses are reused for all observed instances.
&lt;br /&gt;
&lt;br /&gt;Also, declaring an instance variable on this new dynamic class would not work because the object instance being observed is already created (only the isa pointer is changed) and thus would require reallocating the object. 
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">ebce717cf0e062b9bcff42973a660a09</guid><pubDate>Mon, 23 May 2011 16:37:16 GMT</pubDate></item><item><title>mikeash - 2011-05-19 22:45:58</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>I haven't actually looked at the real implementation, but I assume that there is a global table somewhere which maps instances to observer info. The KVO subclass would actually be a good place to store such a table, too.</description><guid isPermaLink="true">8ff47b6bb4366b42eb1291e77244f755</guid><pubDate>Thu, 19 May 2011 22:45:58 GMT</pubDate></item><item><title>Paulo Andrade - 2011-05-19 10:02:16</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>One thing that is not clear is where are the references to the observers stored? 
&lt;br /&gt;
&lt;br /&gt;The observed instance must store these somewhere, and NsObject has no ivars for this
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">5ea9b8bbe33f04cbc858b659eab719b4</guid><pubDate>Thu, 19 May 2011 10:02:16 GMT</pubDate></item><item><title>mikeash - 2009-01-24 08:35:47</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>That'll teach me to make such assertions without testing them! Thanks for correcting me. I modified my code and tested it out and, you're right, KVO notifications are generated even for custom structs.
&lt;br /&gt;
&lt;br /&gt;The __forwarding_prep_0___ function is part of the -forwardInvocation: machinery. It appears that KVO uses the NSInvocation support to package up the parameters being passed in. This allows it to support any type that the forwarding machinery can understand, which should be everything. Presumably the fixed functions that can be found in Foundation exist as an optimization for common types, with the forwarding stuff as a backup for everything else.
&lt;br /&gt;
&lt;br /&gt;Thanks, I learned something!</description><guid isPermaLink="true">99b2f136797ffe0699eafb741ba30ef2</guid><pubDate>Sat, 24 Jan 2009 08:35:47 GMT</pubDate></item><item><title>Ashley Clark - 2009-01-24 07:48:55</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>So, I modified your code to perform some KVO on a struct and the resulting selector for the overridden structure setter that I'm getting back is confounding me:
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;
&lt;br /&gt;(gdb) p (IMP)0x90bca9a0
&lt;br /&gt;$1 = (IMP) 0x90bca9a0 &amp;lt;__forwarding_prep_0___&amp;gt;
&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;</description><guid isPermaLink="true">28deaf98d273b795a77405fad95c7b55</guid><pubDate>Sat, 24 Jan 2009 07:48:55 GMT</pubDate></item><item><title>Ashley Clark - 2009-01-24 07:33:30</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-23.html#comments</link><description>At least according to the Leopard Foundation Release Notes, KVO does now support arbitrary types. So something else must be going on in that case. Automatic boxing in NSValue maybe?
&lt;br /&gt;
&lt;br /&gt;&lt;a href="http://developer.apple.com/ReleaseNotes/Cocoa/Foundation.html"&gt;http://developer.apple.com/ReleaseNotes/Cocoa/Foundation.html&lt;/a&gt;</description><guid isPermaLink="true">5d0dd3b5a5f27c175f427f2b06b61b93</guid><pubDate>Sat, 24 Jan 2009 07:33:30 GMT</pubDate></item></channel></rss>
