<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>mikeash.com pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html comments</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>mikeash.com Recent Comments</description><lastBuildDate>Sun, 12 Apr 2026 03:15:53 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>ihar - 2017-08-23 20:06:17</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Nowadays on 64bit IOS BOOL is &lt;b&gt;_Bool&lt;/b&gt; and not &lt;b&gt;signed char&lt;/b&gt;.
&lt;br /&gt;So, &lt;code&gt;
&lt;br /&gt;if (someObject) {
&lt;br /&gt;}
&lt;br /&gt;&lt;/code&gt; is not a problem anymore.
&lt;br /&gt;&lt;a href="https://stackoverflow.com/questions/31267325/bool-with-64-bit-on-ios/31267502"&gt;https://stackoverflow.com/questions/31267325/bool-with-64-bit-on-ios/31267502&lt;/a&gt;</description><guid isPermaLink="true">45271d4f01df80956b4f198872599961</guid><pubDate>Wed, 23 Aug 2017 20:06:17 GMT</pubDate></item><item><title>Safewiper - 2014-11-13 01:01:34</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>As a programmer familiar with C++, Java and Objective-C, I have to say OC seem much easier than the other two from the experience of novice developer. It's great to read in-depth analysis like this one.</description><guid isPermaLink="true">68f8c3fbcd3287b35b879f98c167e7e4</guid><pubDate>Thu, 13 Nov 2014 01:01:34 GMT</pubDate></item><item><title>Ben - 2013-01-23 18:31:02</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>@Stephen - I assumed he left the initialization out for brevity (since it may be an ivar, extern, static, etc.) and was simply providing us the type.
&lt;br /&gt;
&lt;br /&gt;It might be the case that result pointer will be garbage, but it might also be nil depending on how it is defined, luck, what type of build, etc.
&lt;br /&gt;
&lt;br /&gt;This is the problem with pseudocode, there can be a number of "issues" that aren't really issues at all depending on if we have all the context or not.  So we are all simultaneously correct and incorrect :)</description><guid isPermaLink="true">94388e3797ec009c8393f583de6dc786</guid><pubDate>Wed, 23 Jan 2013 18:31:02 GMT</pubDate></item><item><title>Mark Aufflick - 2013-01-16 04:42:04</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Of course, if you happened to have a method called "isNotEqualTo:" then the behaviour would be problematic, and a good reason not to have a method that operates that way around!</description><guid isPermaLink="true">0cb2027de5551417d6d3b87cbad8aafa</guid><pubDate>Wed, 16 Jan 2013 04:42:04 GMT</pubDate></item><item><title>Mark Aufflick - 2013-01-16 04:40:20</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>I would say that:
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;[nil isEqual: nil] == NO&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;Is in fact exactly what I would expect, equating nil with an SQL-like concept of no/null value, and that a null value cannot equal anything, not even another null value.</description><guid isPermaLink="true">da4ae4bfbec6ad4ad9d5bb844a7aa51a</guid><pubDate>Wed, 16 Jan 2013 04:40:20 GMT</pubDate></item><item><title>Sean M - 2013-01-04 15:44:04</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Stephen, under ARC, "NSMutableArray *result" doesn't give a pointer filled with a garbage address, it is initialized to nil.</description><guid isPermaLink="true">6d0f68bb20641fb5b7bd3ff72746c287</guid><pubDate>Fri, 04 Jan 2013 15:44:04 GMT</pubDate></item><item><title>Stephen Lottermoser - 2013-01-04 00:32:40</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>@Ben Isn't @MWS's real problem that he forgot to initialize the result array? &lt;code&gt;NSMutableArray *result;&lt;/code&gt; would give a pointer filled with garbage instead of a valid mutable array object, so adding objects to it and the returning an autoreleased object would fail and most likely crash the app.</description><guid isPermaLink="true">42c41cac680dc6fbda835435058c6222</guid><pubDate>Fri, 04 Jan 2013 00:32:40 GMT</pubDate></item><item><title>Ben - 2012-12-28 05:05:44</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>@MWS - Technically you are returning an autoreleased array, not an empty one.  If the method that called this one retains the array then it will not be collected when the run loop executes next (or whenever the containing autorelease pool is drained).</description><guid isPermaLink="true">77ef6b86c6da5fa0eb8fa8be401549ff</guid><pubDate>Fri, 28 Dec 2012 05:05:44 GMT</pubDate></item><item><title>jamie - 2012-12-23 18:22:00</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Is it possible to write your own user-created static checks rules for Clang/LLVM, without going down into the source or writing a plugin?  Something simple like TDK's -- "never allow a function to return a __block type" or some such.</description><guid isPermaLink="true">05ec0adb018dd7e78fae11dc10c0a039</guid><pubDate>Sun, 23 Dec 2012 18:22:00 GMT</pubDate></item><item><title>Sean M - 2012-12-22 02:03:28</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>The fact that BOOL has 256 values is maddening.  Regarding this, I would also suggest one never compare BOOL variables against YES.  ie:
&lt;br /&gt;
&lt;br /&gt;BOOL foo = ComputeSomething()
&lt;br /&gt;if (foo == YES)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;...
&lt;br /&gt;
&lt;br /&gt;Hopefully clang will warn on this one day: &amp;lt;&lt;a href="http://llvm.org/PR9194&amp;amp;gt"&gt;http://llvm.org/PR9194&amp;gt;&lt;/a&gt;;.  Until then, at least searching your codebase for "== YES" is not so hard.</description><guid isPermaLink="true">46ef3fa1889ad1062af90bbbc988bbdc</guid><pubDate>Sat, 22 Dec 2012 02:03:28 GMT</pubDate></item><item><title>mikeash - 2012-12-19 23:53:44</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>&lt;b&gt;John Brewer:&lt;/b&gt; This is definitely something that happens, as running into it recently is what prompted me to add it to this list. It looks like it's configurable, and since it's global state, you can't rely on it being set to anything in particular unless you own everything in your process.</description><guid isPermaLink="true">7d97a92d16de33e3f60e0144492476fd</guid><pubDate>Wed, 19 Dec 2012 23:53:44 GMT</pubDate></item><item><title>John Brewer - 2012-12-19 12:23:15</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Is EINTR handling an issue on iOS and modern MacOS?  I was under the impression that BSD handled retries on signals automagically.</description><guid isPermaLink="true">4a8bd8130b4a15378a8be054bae2976a</guid><pubDate>Wed, 19 Dec 2012 12:23:15 GMT</pubDate></item><item><title>TDK - 2012-12-17 21:55:03</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Threaded code pitfalls should be an article all of its own, but here's one Objective-C makes trivial to typo or misunderstand.
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;- (NSString *)newString {
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;__block NSString *returnString = nil;
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dispatch_async(dispatch_get_main_queue(), ^{
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;returnString = [[NSString alloc] initWithFormat:@"Expensive String"];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return returnString;
&lt;br /&gt;}
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;- When does -newString return? Almost immediately.
&lt;br /&gt;- When does returnString get initialized? Um, whenever.
&lt;br /&gt;- When does returnString get released? WAT</description><guid isPermaLink="true">a3d823dfbd35a41b84d897af34e61642</guid><pubDate>Mon, 17 Dec 2012 21:55:03 GMT</pubDate></item><item><title>mikeash - 2012-12-16 01:53:10</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>&lt;b&gt;Raphael:&lt;/b&gt; Object allocation is cheap. You have to allocate memory for the UTF-8 string regardless, so it's probably not much more. For if(object), it's fine. That's equivalent to != 0 which is the same as != NULL.</description><guid isPermaLink="true">f510ec04d10553fd8415c4b197a7b915</guid><pubDate>Sun, 16 Dec 2012 01:53:10 GMT</pubDate></item><item><title>Grigory Entin - 2012-12-15 23:35:40</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>I do believe that at least the latest versions of clang are able to complain about (BOOL)object. It does not look like a problem to me.
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;error: cast from pointer to smaller type 'BOOL' (aka 'signed char') loses information
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BOOL x = (BOOL)object;
&lt;br /&gt;&lt;/code&gt;</description><guid isPermaLink="true">c431c8ccd38731f0c0a2569360d14057</guid><pubDate>Sat, 15 Dec 2012 23:35:40 GMT</pubDate></item><item><title>Raphael - 2012-12-15 12:01:40</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>@mikeash: Yeah, I saw &lt;code&gt;-dataUsingEncoding&lt;/code&gt; as well. How much overhead is there to using the NSData wrapper?
&lt;br /&gt;
&lt;br /&gt;Also, regarding the “casting objects to BOOL” issue: does this pitfall still hold true when doing something like &lt;code&gt;if(object) {…&lt;/code&gt;? I gather C uses int for the comparison happening in the if. What if pointers were longer than the standard int type, would that be a problem then? Are there any platforms where this is the case?</description><guid isPermaLink="true">00e0c7dec8ce7349f4f572d85ca2b738</guid><pubDate>Sat, 15 Dec 2012 12:01:40 GMT</pubDate></item><item><title>Greg Parker - 2012-12-15 09:15:37</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Recent versions of clang warn about that "missing method argument" example. If you really want an unnamed method argument then the compiler will insist that you add some whitespace. </description><guid isPermaLink="true">e0775c214cb801ad2d4a758b44baab03</guid><pubDate>Sat, 15 Dec 2012 09:15:37 GMT</pubDate></item><item><title>Rob Mayoff - 2012-12-14 22:20:25</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Some methods in Cocoa only work reliably for BOOL values of 0 and 1.  See &lt;a href="http://stackoverflow.com/questions/13750370/button-set-selected-via-bool/13750834#13750834"&gt;http://stackoverflow.com/questions/13750370/button-set-selected-via-bool/13750834#13750834&lt;/a&gt; .  So even if you get lucky and your pointer gets clipped to a non-zero value, it may still be treated incorrectly later.</description><guid isPermaLink="true">64ce2a39352a206370c668d74773e432</guid><pubDate>Fri, 14 Dec 2012 22:20:25 GMT</pubDate></item><item><title>Jeff Johnson - 2012-12-14 19:10:30</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Actually, -isEqual: is documented as accepting nil, although unfortunately that documentation is not in the NSObject protocol reference. "However, for backward compatibility, isEqual: methods of the Cocoa frameworks do accept nil, returning NO." 
&lt;br /&gt;&lt;a href="https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW61"&gt;https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW61&lt;/a&gt;</description><guid isPermaLink="true">a5266bb32a0be91ac874f7f37dcab4d2</guid><pubDate>Fri, 14 Dec 2012 19:10:30 GMT</pubDate></item><item><title>BDB - 2012-12-14 18:41:12</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>A note: your solution for EINTR could cause some oddities if a signal handler is blocking SIGTERM, SIGQUIT, etc to do cleanup.
&lt;br /&gt;
&lt;br /&gt;E.G. If you are in a loop reading/writing gigs of data your app could stay alive well past the intended short cleanup delay. You'd have to watch a flag set by the signal handler to exit the I/O loop for a complete solution.</description><guid isPermaLink="true">208771ba0ff0db8de47f866484bb450b</guid><pubDate>Fri, 14 Dec 2012 18:41:12 GMT</pubDate></item><item><title>mikeash - 2012-12-14 17:05:06</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>&lt;b&gt;Raphael:&lt;/b&gt; This is what the &lt;code&gt;-dataUsingEncoding:&lt;/code&gt; method is for. It gives you a &lt;code&gt;NSData&lt;/code&gt; object which encapsulates both the bytes and the length.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;bealex:&lt;/b&gt; The problem only happens if you write &lt;code&gt;i &amp;gt;= 0&lt;/code&gt;, and any decent C compiler will warn you that the comparison is always true if you have warnings turned up to decent levels.</description><guid isPermaLink="true">e099e31c60d8cdd0d684decb01fac3b8</guid><pubDate>Fri, 14 Dec 2012 17:05:06 GMT</pubDate></item><item><title>bealex - 2012-12-14 17:02:00</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>I personally hate unsigned ints in length and count. (Yes, I know, I'm from Java world, but does that matter?) Every now and then I create some loop like "i &amp;gt; 0; i--" and if "i" happens to be unsigned, it blows up with nasty errors.</description><guid isPermaLink="true">3f0236b9031ee9fa6225d64416b26800</guid><pubDate>Fri, 14 Dec 2012 17:02:00 GMT</pubDate></item><item><title>MWS - 2012-12-14 16:53:07</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>Here's a nice one that happened to me the other day:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;
&lt;br /&gt;NSMutableArray * result;
&lt;br /&gt;
&lt;br /&gt;[result addObject:someObject]; 
&lt;br /&gt;//... add a bunch of objects
&lt;br /&gt;
&lt;br /&gt;return [NSArray arrayWithArray:result];
&lt;br /&gt;
&lt;br /&gt;&lt;/code&gt;
&lt;br /&gt;Which returns an empty array.   :(
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">933c167dc4326a1e2e72d34ef04848dd</guid><pubDate>Fri, 14 Dec 2012 16:53:07 GMT</pubDate></item><item><title>Raphael - 2012-12-14 15:42:40</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2012-12-14-objective-c-pitfalls.html#comments</link><description>What has always bothered me about the &lt;code&gt;- (const char *)UTF8String&lt;/code&gt; method of &lt;code&gt;NSString&lt;/code&gt; is that it needs to calculate the number of bytes that the string will take in UTF-8 but there is no way to get that information out of there so you need to call &lt;code&gt;strlen&lt;/code&gt;, which calculates the same information again, again taking a time of O(n).
&lt;br /&gt;
&lt;br /&gt;A method like &lt;code&gt;- (const char *)UTF8String returnedBytes:(* int)byteCount&lt;/code&gt; would be very helpful. You could then rewrite your example as follows:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;int byteCount;
&lt;br /&gt;const char *cStr = [string UTF8String returnedBytes:&amp;amp;byteCount];
&lt;br /&gt;write(fd, cStr, byteCount);&lt;/code&gt;</description><guid isPermaLink="true">877e63376b036f97e4eff4c3e6bd9e23</guid><pubDate>Fri, 14 Dec 2012 15:42:40 GMT</pubDate></item></channel></rss>
