{"id":670,"date":"2010-08-19T05:01:01","date_gmt":"2010-08-19T10:01:01","guid":{"rendered":"http:\/\/vgable.com\/blog\/?p=670"},"modified":"2010-09-17T15:22:43","modified_gmt":"2010-09-17T20:22:43","slug":"the-most-useful-objective-c-code-ive-ever-written","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2010\/08\/19\/the-most-useful-objective-c-code-ive-ever-written\/","title":{"rendered":"The Most Useful Objective-C Code I&#8217;ve Ever Written"},"content":{"rendered":"<p>Actually, it&#8217;s the most useful code I&#8217;ve <em>extended<\/em>; credit for the core idea goes to <a href=\"http:\/\/www.dribin.org\/dave\/\">Dave Dribin<\/a> with his <a href=\"http:\/\/www.dribin.org\/dave\/blog\/archives\/2008\/09\/22\/convert_to_nsstring\/\"><cite>Handy NSString Conversion Macro<\/cite><\/a>.<\/p>\n<p><strong><code><a href=\"\">LOG_EXPR<\/a>(x)<\/code> is a macro that prints out <code>x<\/code>, no matter what type <code>x<\/code> is<\/strong>, without having to worry about format-strings (and related crashes from eg. printing a C-string the same way as an <code>NSString<\/code>). It works on Mac OS X and iOS. Here are some examples,<\/p>\n<p><code>LOG_EXPR(self.window.screen);<\/code><\/p>\n<blockquote><p>self.window.screen = &lt;UIScreen: 0x6d20780; bounds = {{0, 0}, {320, 480}}; mode = &lt;UIScreenMode: 0x6d20c50; size = 320.000000 x 480.000000&gt;&gt;\n<\/p><\/blockquote>\n<p><code>LOG_EXPR(self.tabBarController.viewControllers);<\/code><\/p>\n<blockquote><p>self.tabBarController.viewControllers = (<br \/>\n    &#8220;&lt;UINavigationController: 0xcd02e00&gt;&#8221;,<br \/>\n    &#8220;&lt;SavingsViewController: 0xcd05c40&gt;&#8221;,<br \/>\n    &#8220;&lt;SettingsViewController: 0xcd05e90&gt;&#8221;<br \/>\n)<\/p><\/blockquote>\n<p>Pretty straightforward, really. The biggest convenience so far is having the expression printed out, so you don&#8217;t have to write out a name redundantly in the format string (eg. <code> NSLog(@\"actionURL = %@\", actionURL)<\/code>). But <code>LOG_EXPR<\/code> really shows it&#8217;s worth when you start using scalar or <code>struct<\/code> expressions:<\/p>\n<p><code>LOG_EXPR(self.window.windowLevel);<\/code><\/p>\n<blockquote><p>self.window.windowLevel = 0.000000<\/p><\/blockquote>\n<p><code>LOG_EXPR(self.window.frame.size);<\/code><\/p>\n<blockquote><p>self.window.frame.size = {320, 480}<\/p><\/blockquote>\n<p>Yes, there are expressions that won&#8217;t work, but they&#8217;re pretty rare for me. I use <code>LOG_EXPR<\/code> every day. Several times. It&#8217;s not quite as good as having <a href=\"http:\/\/vgable.com\/blog\/2010\/06\/14\/ask-f-script\/\">a REPL for Cocoa<\/a>, but it&#8217;s handy.<\/p>\n<p><a href=\"#Get_LOG_EXPR\">Give it a try<\/a>.<\/p>\n<h3>How It Works<\/h3>\n<p>The problem is how to pick a function or format string to print <code>x<\/code>, based on the type of <code>x<\/code>. C++&#8217;s type-based dispatch would be a good fit here, but it&#8217;s verbose (a full function-definition per type) and I wanted to use pure Objective-C if possible. Fortunately, <strong>Objective-C has an <a href=\"http:\/\/developer.apple.com\/mac\/library\/documentation\/cocoa\/conceptual\/ObjCRuntimeGuide\/Articles\/ocrtTypeEncodings.html\"><code>@encode()<\/code><\/a>  compiler directive that returns a string describing any type it&#8217;s given.<\/strong> Unfortunately it works on <em>types<\/em>, not variables, but with C99 <strong>the <code><a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Typeof.html\">typeof()<\/a><\/code> compiler directive lets us get the type of any variable<\/strong>, which we can pass to <code>@encode()<\/code>.  The final bit of compiler magic is using <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/cpp\/Stringification.html\">stringification (<code>#<\/code>)<\/a> to print out the literal string inside <code>LOG_EXPR()<\/code>&#8216;s parenthesis.<\/p>\n<h3>The Macro, Line By Line<\/h3>\n<div class=\"code-box\">\n<pre>\n1 #define LOG_EXPR(_X_) do{\\\n2 \t__typeof__(_X_) _Y_ = (_X_);\\\n3 \tconst char * _TYPE_CODE_ = @encode(__typeof__(_X_));\\\n4 \tNSString *_STR_ = VTPG_DDToStringFromTypeAndValue(_TYPE_CODE_, &_Y_);\\\n5 \tif(_STR_)\\\n6 \t\tNSLog(@\"%s = %@\", #_X_, _STR_);\\\n7 \telse\\\n8 \t\tNSLog(@\"Unknown _TYPE_CODE_: %s for expression %s in function %s, file %s, line %d\", _TYPE_CODE_, #_X_, __func__, __FILE__, __LINE__);\\\n9 }while(0)\n<\/pre>\n<\/div>\n<ol>\n<li>The first and last lines are a way to put <code>{}<\/code>&#8216;s around the macro to prevent <a href=\"http:\/\/en.wikipedia.org\/wiki\/C_preprocessor#Multiple_statements\">unintended effects<\/a>. The <code>do{}while(0);<\/code> &#8220;loop&#8221; does nothing else.<\/li>\n<li>First evaluate the expression, <code>_X_<\/code>, given to <code>LOG_EXPR<\/code> <em>once<\/em>, and store the result in a <code>_Y_<\/code>. We need to use <code><a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Typeof.html\">typeof()<\/a><\/code> (which had to be written <code>__typeof__()<\/code> to appease some versions of GCC) to figure out the type of <code>_Y_<\/code>.<\/li>\n<li><code>_TYPE_CODE_<\/code> is c-string that <a href=\"http:\/\/developer.apple.com\/mac\/library\/documentation\/cocoa\/conceptual\/ObjCRuntimeGuide\/Articles\/ocrtTypeEncodings.html\">describes the type<\/a> of the expression we want to print out.<\/li>\n<li>Now we have enough information to call a function, <code>VTPG_DDToStringFromTypeAndValue()<\/code> to convert the expression&#8217;s value to a string. We pass it the <code>_TYPE_CODE_<\/code> string, and <em>the address of <\/em> <code>_Y_<\/code>, which is a pointer, and has a known size. We can&#8217;t pass <code>_Y_<\/code> directly, because depending on what <code>_X_<\/code> is, it will have different types and could be of any size.<\/li>\n<li><code>VTPG_DDToStringFromTypeAndValue()<\/code> returns <code>nil<\/code> if it can&#8217;t figure out how to convert a value to a string.<\/li>\n<li>Everything went well, print the <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/cpp\/Stringification.html\">stringified<\/a> expression, <code>#_X_<\/code>, and  the string representing it&#8217;s value, <code>_STR_<\/code>.<\/li>\n<li>otherwise\u2026<\/li>\n<li>The expression had a type we can&#8217;t handle, print out a verbose diagnostic message.<\/li>\n<li>See line 1.<\/li>\n<\/ol>\n<h3>The <code>VTPG_DDToStringFromTypeAndValue()<\/code> Function<\/h3>\n<p>See the source in <a href=\"http:\/\/github.com\/VTPG\/CommonCode\/blob\/master\/VTPG_Common.m\">VTPG_Common.m<\/a>:<\/p>\n<p><iframe src =\"http:\/\/github.com\/VTPG\/CommonCode\/blob\/master\/VTPG_Common.m\" width=\"100%\" height=\"300\">(Your browser does not support iframes.)<\/iframe><\/p>\n<p>It&#8217;s derived from  <a href=\"http:\/\/www.dribin.org\/dave\/\">Dave Dribin<\/a>&#8216;s function <a href=\"http:\/\/www.dribin.org\/dave\/blog\/archives\/2008\/09\/22\/convert_to_nsstring\/\"> <code>DDToStringFromTypeAndValue()<\/code><\/a>, and is pretty straightforward: <code>strcmp()<\/code> the type-string, and if it matches a known type call a function, or use <code>+[NSString stringWithFormat]:<\/code>, to turn the value into a string.<\/p>\n<h3>The First Step Twords Fixing Your Macro Problem is Admitting it&#8230;<\/h3>\n<p>So yeah, maybe I went a little wild with macros here\u2026<\/p>\n<p>But it took out some <a href=\"http:\/\/en.wikipedia.org\/wiki\/Don't_repeat_yourself\">WET<\/a>-ness of the original code, and prevents me from accidentally mixing up types in a long wall of <code>if<\/code>s, eg.<\/p>\n<div class=\"code-box\">\n<pre>\nelse if (strcmp(typeCode, @encode(NSRect)) == 0)\n{\n    return NSStringFromRect(*(NSRange *)value);\n}\nelse if (strcmp(typeCode, @encode(NSRange)) == 0)\n{\n    return NSStringFromRect(*(NSRange *)value);\n}\n<\/pre>\n<\/div>\n<p>If I were cool, I&#8217;d use <code>NSDictionary<\/code>s to map from the <code>@encode<\/code>-string to an appropriate format string or function pointer.  This is conceptually cleaner; less error-prone than using macros; and almost certainly faster. Unfortunately, it gets a little tricky with functions, since I need to deference <code>value<\/code> into the proper type.<\/p>\n<p>One final note from my testing, I could do away with the <code>strcmp()<\/code>s, because directly comparing <code>@encode<\/code> string pointers (eg <code>if(typeCode == @encode(NSString*))<\/code> works. I don&#8217;t know if it will <em>always<\/em> work though, so relying on it strikes me as a profoundly Bad Idea. But maybe that bad idea will give someone a good idea.<\/p>\n<h3>Limitations<\/h3>\n<h4>Arrays<\/h4>\n<p>C arrays generally muck things up. Casting to a pointer works around this:<\/p>\n<div class=\"code-box\">\n<pre>\nchar x[14] = \"Hello, world!\";\n\/\/LOG_EXPR(x); \/\/error: invalid initializer\nLOG_EXPR((char*)x); \/\/prints fine\n<\/pre>\n<\/div>\n<h4><code>__func__<\/code><\/h4>\n<p>Because it is a <code>static const char []<\/code>, <code><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2004\/n1642.html\">__func__<\/a><\/code> (and <code>__FUNCTION__<\/code> or <code>__PRETTY_FUNCTION__<\/code>) need casting to <code>char*<\/code> to work with <code>LOG_EXPR<\/code>. Because logging out a function\/method call is something I do frequently, I use the macro:<\/p>\n<div class=\"code-box\">\n<pre>\n#define LOG_FUNCTION()\tNSLog(@\"%s\", __func__)<\/pre>\n<\/div>\n<h4><code>long double<\/code> (Leopard and older)<\/h4>\n<p>On older systems, <code>LOG_EXPR<\/code> won&#8217;t work with a <code>long double<\/code> value, because <code>@encode(long double)<\/code> gives the same result as <code>@encode(double)<\/code>. This is a <a href=\"http:\/\/openradar.appspot.com\/6468314\">known issue<\/a> with the runtime. The top-level <code>LOG_EXPR<\/code> macro could detect a <code>long double<\/code> with <code>if((sizeof(_X_) == sizeof(long double)) && (_TYPE_CODE_ == @encode(double)))<\/code>. But I doubt this will ever be necessary.<\/p>\n<p>I haven&#8217;t actually written any code that uses <code>long double<\/code>, because I <strong>use <code><a href=\"http:\/\/developer.apple.com\/mac\/library\/documentation\/Cocoa\/Reference\/Foundation\/Miscellaneous\/Foundation_Functions\/Reference\/reference.html#\/\/apple_ref\/doc\/uid\/20000055-BCIHCEFJ\">NSDecimal<\/a><\/code>, or another base-10 number format, for situations that require more precision than a <code>double<\/code>.<\/strong><\/p>\n<h3>Scaling and Frameworks <\/h3>\n<p>Growing <code>LOG_EXPR<\/code> to handle <em>every<\/em> type is a lot of work. I&#8217;ve only added types that I&#8217;ve actually needed to print. This has kept the code manageable, and seems to be working so far.<\/p>\n<p>The biggest problem I have is <strong>how to deal with types that are in frameworks that not every project includes<\/strong>. Projects that use CoreLocation.framework need to be able to use <code>LOG_EXPR<\/code> to print out CoreLocation specific <code>struct<\/code>s, like <code> CLLocationCoordinate2D<\/code>. But projects that <em>don&#8217;t<\/em> use CoreLocation.framework don&#8217;t have a definition of the <code>CLLocationCoordinate2D<\/code> type, so code to convert it to a string won&#8217;t compile. There are two ways I&#8217;ve tried to solve the problem<\/p>\n<h4>Comment-out framework-specific code<\/h4>\n<p>This is pretty self-explanatory, I&#8217;ll fork VTPG_Common.m and un-comment-out code for types that my project needs to print. It works, but it&#8217;s drudgery. Programmers hate that.<\/p>\n<h4>Hardcode type info<\/h4>\n<p>The idea is to hard-code the string that <code>@encode(SomeType)<\/code> would evaluate to, and then (since we know how <code>SomeType<\/code> is laid out in memory) use casting and pointer-arithmetic to get at the fields.<\/p>\n<p>For example:<\/p>\n<div class=\"code-box\">\n<pre>\n\/\/This is a hack to print out CLLocationCoordinate2D, without needing to #import &lt;CoreLocation\/CoreLocation.h&gt;\n\/\/A CLLocationCoordinate2D is a struct made up of 2 doubles.\n\/\/We detect it by hard-coding the result of @encode(CLLocationCoordinate2D).\n\/\/We get at the fields by treating it like an array of doubles, which it is identical to in memory.\nif(strcmp(typeCode, \"{?=dd}\")==0)\/\/@encode(CLLocationCoordinate2D)\n\treturn [NSString stringWithFormat:@\"{latitude=%g,longitude=%g}\",((double*)value)[0],((double*)value)[1]];\n<\/pre>\n<\/div>\n<p>This Just Works in a project that includes CoreLocation, and doesn&#8217;t mess up projects that don&#8217;t. Unfortunately it&#8217;s <em>horribly brittle<\/em>. Any Xcode or system update could break it. It&#8217;s not a tenable fix.<\/p>\n<h3>Areas for Improvement<\/h3>\n<p>If there&#8217;s some type <code>LOG_EXPR<\/code> can&#8217;t handle that you need, please <a href=\"http:\/\/github.com\/VTPG\/CommonCode\">jump right in and improve it<\/a>!<\/p>\n<p>When I have time, I plan to write a general parser for <code>@encode()<\/code>-strings. This will let me print out <em>any<\/em> <code>struct<\/code>, which mostly solves the type-defined-in-missing-framework problem, and would let <code>LOG_EXPR<\/code> Just Work with types from all kinds of POSIX\/C libraries.<\/p>\n<h3><a name=\"Get_LOG_EXPR\"><\/a>Using <code>LOG_EXPR()<\/code> in Your Project <\/h3>\n<p>Download <a href=\"http:\/\/github.com\/VTPG\/CommonCode\/blob\/master\/VTPG_Common.m\">VTPG_Common.m<\/a> and <a href=\"http:\/\/github.com\/VTPG\/CommonCode\/blob\/master\/VTPG_Common.h\">VTPG_Common.h<\/a> from <a href=\"http:\/\/github.com\/VTPG\/CommonCode\">my github repository<\/a>, and add them to your Xcode project.<\/p>\n<p>Now just add the line <code>#import \"VTPG_Common.h\"<\/code> to your prefix file (named <code>&lt;ProjectName&gt;_Prefix.pch<\/code> by default), after the <code>#ifdef __OBJC__<\/code>, for example:<\/p>\n<div class=\"code-box\">\n<pre>\n#ifdef __OBJC__\n    #import &lt;Foundation\/Foundation.h&gt;\n    \/\/ maybe other files, depending on project  template...\n    #import \"VTPG_Common.h\"\n#endif<\/pre>\n<\/div>\n<p>Now <code>LOG_EXPR()<\/code> will work everywhere in your project.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Actually, it&#8217;s the most useful code I&#8217;ve extended; credit for the core idea goes to Dave Dribin with his Handy NSString Conversion Macro. LOG_EXPR(x) is a macro that prints out x, no matter what type x is, without having to worry about format-strings (and related crashes from eg. printing a C-string the same way as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53,18,203,3,5,4,11,13],"tags":[613,77,611,80,83,612,230],"class_list":["post-670","post","type-post","status-publish","format-standard","hentry","category-announcement","category-bug-bite","category-iphone","category-macosx","category-objective-c","category-programming","category-research","category-sample-code","tag-c","tag-debugging","tag-log_expr","tag-macros","tag-nslog","tag-preprocessor","tag-printf"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/670","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=670"}],"version-history":[{"count":23,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/670\/revisions"}],"predecessor-version":[{"id":695,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/670\/revisions\/695"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=670"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=670"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=670"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}