{"id":296,"date":"2009-04-19T10:42:05","date_gmt":"2009-04-19T15:42:05","guid":{"rendered":"http:\/\/vgable.com\/blog\/2009\/04\/19\/beware-rangeof-nsstring-operations\/"},"modified":"2009-04-22T20:52:02","modified_gmt":"2009-04-23T01:52:02","slug":"beware-rangeof-nsstring-operations","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2009\/04\/19\/beware-rangeof-nsstring-operations\/","title":{"rendered":"Beware rangeOf NSString Operations"},"content":{"rendered":"<p>I have repeatedly had trouble with the <a href=\"http:\/\/developer.apple.com\/DOCUMENTATION\/Cocoa\/Reference\/Foundation\/Classes\/NSString_Class\/Reference\/NSString.html#\/\/apple_ref\/occ\/instm\/NSString\/rangeOfCharacterFromSet:\"><code>rageOf<\/code>&#8230; <code>NSString<\/code> methods<\/a>, because they return a <code>struct<\/code>. Going forward I will do more to avoid them, here are some ways I plan to do it.<\/p>\n<p><a href=\"http:\/\/vgable.com\/blog\/2008\/05\/31\/messages-to-nowhere\/\">Sending a message that returns a <code>struct<\/code> to <code>nil<\/code> can &#8220;return&#8221; <em>undefined<\/em> values<\/a>. With small <code>struct<\/code>s like <code>NSRange<\/code>, you are more likely to get <code>{0}<\/code> on Intel, compared to PowerPC and iPhone\/ARM. Unfortunately, this makes <code>nil<\/code>-messaging bugs hard to detect.  In my experience <strong>you will miss them when running on the simulator, even if they are 100% reproducible on an actual iPhone<\/strong>.<\/p>\n<p>This category method has helped me avoid using <code>-rangeOfString:<\/code> dangerously,<\/p>\n<pre>\n@implementation NSString  (HasSubstring)\n- (BOOL) hasSubstring:(NSString*)substring;\n{\n\tif(<a href=\"http:\/\/vgable.com\/blog\/2008\/12\/16\/isempty\/\">IsEmpty<\/a>(substring))\n\t\treturn NO;\n\tNSRange substringRange = [self rangeOfString:substring];\n\treturn substringRange.location != NSNotFound && substringRange.length &gt; 0;\n}\n@end\n<\/pre>\n<p>I choose to define <code>[aString hasSubstring:@\"\"]<\/code> as <code>NO<\/code>. You might prefer to throw an exception, or differentiate between <code>@\"\"<\/code> and <code>nil<\/code>. But I don&#8217;t think a <code>nil<\/code> string is enough error to throw an exception. And even though technically any string contains the empty string, I generally treat <code>@\"\"<\/code> as semantically equivalent to <code>nil<\/code>.<\/p>\n<p>As <a href=\"http:\/\/vgable.com\/blog\/2008\/05\/31\/messages-to-nowhere\/\">I&#8217;ve said before<\/a>,<\/p>\n<blockquote><p>A few simple guidelines can help you avoid my misfortune:<\/p>\n<ul>\n<li> Be especially careful using of any objective-C method that returns a <code>double, struct,<\/code> or <code>long long<\/code>\n<li> Don&#8217;t write methods that return a <code>double<\/code>, <code>struct<\/code>, or<code>long long<\/code>.  Return an object instead of a <code>struct<\/code>; an <a href=\"http:\/\/developer.apple.com\/documentation\/Cocoa\/Reference\/Foundation\/Classes\/NSNumber_Class\/Reference\/Reference.html\"><code>NSNumber*<\/code><\/a> or <code>float<\/code> instead of a <code>double<\/code> or <code>long long<\/code>.  If you must return a dangerous data type, then see if you can avoid it. There really isn&#8217;t a good reason to return a <code>struct<\/code>, except for efficiency. And when micro-optimizations like that matter, it makes more sense to write that procedure in straight-C, which avoids the overhead of Objective-C message-passing, and solves the undefined-return-value problem.\n<li> But if you absolutely must return a dangerous data type, then return it in a parameter. That way you can give it a default value of your choice, and won&#8217;t have undefined values if an object is unexpectedly <code>nil<\/code>.<br \/>\nBad:<br \/>\n<code>- (struct CStructure) evaluateThings;<\/code><br \/>\nGood:<br \/>\n<code>- (void) resultOfEvaluatingThings:(struct CStructure*)result;<\/code>.\n<\/ul>\n<\/blockquote>\n<p>It&#8217;s not a bad idea to wrap up all the <code>rangeOf<\/code> methods in functions or categories that play safer with <code>nil<\/code>.<\/p>\n<p><small>Thanks to <a href=\"http:\/\/www.sealiesoftware.com\/\">Greg Parker<\/a> for corrections!<\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have repeatedly had trouble with the rageOf&#8230; NSString methods, because they return a struct. Going forward I will do more to avoid them, here are some ways I plan to do it. Sending a message that returns a struct to nil can &#8220;return&#8221; undefined values. With small structs like NSRange, you are more likely [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,203,5,4,13],"tags":[613,388,78,263,23],"class_list":["post-296","post","type-post","status-publish","format-standard","hentry","category-bug-bite","category-iphone","category-objective-c","category-programming","category-sample-code","tag-c","tag-nsrange","tag-nsstring","tag-objective-c-20","tag-x86"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/296","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/comments?post=296"}],"version-history":[{"count":0,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/296\/revisions"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=296"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=296"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=296"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}