{"id":193,"date":"2015-05-28T19:14:41","date_gmt":"2015-05-28T19:14:41","guid":{"rendered":"http:\/\/brian.cordanyoung.com\/Portfolio\/?p=193"},"modified":"2016-05-16T17:57:54","modified_gmt":"2016-05-16T17:57:54","slug":"manual-reference-counting-and-blocks-puzzle","status":"publish","type":"post","link":"https:\/\/brian.cordanyoung.com\/Portfolio\/manual-reference-counting-and-blocks-puzzle\/","title":{"rendered":"Manual Reference Counting and Blocks puzzle"},"content":{"rendered":"<p>I have &#8216;come of age&#8217; in the ARC era. Although I have done some manual reference counting and think I understand it, I took a test on my Obj-C skills lately and ran across this puzzle. My answer was the simple, obvious and incorrect choice.<\/p>\n<p>To understand it better I created this <a href=\"https:\/\/github.com\/briancordanyoung\/TestRetainCountAndBlocks\">test project<\/a> and picked it apart. Try the puzzle yourself and then read my thoughts below. If you see any errors in my logic, please let me know!<\/p>\n<h4>The Code<\/h4>\n<pre lang=\"objc\">\r\n    \/\/ Test: Once this method is executed, what will be printed to the console?\r\n    NSObject *object = [NSObject new];\r\n    \r\n    dispatch_async(dispatch_get_main_queue(), ^{\r\n      NSLog(@\"A %u\", [object retainCount]);\r\n      \r\n      dispatch_async(dispatch_get_main_queue(), ^{\r\n        NSLog(@\"B %u\", [object retainCount]);\r\n      });\r\n      \r\n      NSLog(@\"C %u\", [object retainCount]);\r\n    });\r\n    \r\n    NSLog(@\"D %u\", [object retainCount]);\r\n<\/pre>\n<h4>The Choices<\/h4>\n<table>\n<tr>\n<td>\n<pre>\r\n<code>1.  D 2\r\n    A 1\r\n    C 2\r\n    B 1\r\n<\/code>\r\n<\/pre>\n<\/td>\n<td>\n<pre>\r\n<code>2.  B 3\r\n    A 2\r\n    C 2\r\n    D 1\r\n<\/code>\r\n<\/pre>\n<\/td>\n<td>\n<pre>\r\n<code>3.  B 1\r\n    A 2\r\n    C 2\r\n    D 1\r\n<\/code>\r\n<\/pre>\n<\/td>\n<td>\n<pre>\r\n<code>4.  D 2\r\n    A 2\r\n    C 3\r\n    B 2\r\n<\/code>\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>The initial mistake I made was not thinking about <strong>when<\/strong> the blocks would be executed.  Because <strong>dispatch_async()<\/strong> was putting the block on the main queue, I read this code as a straight procedural list of commands, and came up with answer #2.  This was completely wrong. I even missed the first clue that the order of the 4 logged lines was just as important as the retain count being printed.<\/p>\n<p>After creating the test project and seeing for myself what the correct answer was I was flumexed. But, quickly I reminded myself that dispatching a block, even on the same queue, will delay the execution of that code until the next run loop.  The 2nd nested block doesn&#8217;t even capture <strong>object<\/strong> (increasing the retain count) until after the first executed <strong>NSLog<\/strong> prints out the retain count for &#8216;D&#8217;.<\/p>\n<p>With the answer #4 clearly true, I could now re-read the code to understand it. I added comments with my thoughts:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n  \/\/ Test: Once this method is executed, what will be printed to the console?\r\n  \/\/ Both the printing\/execution order and retain count are important\r\n\r\n  NSObject *object = [NSObject new];  \/\/ Retain Count: 1\r\n  \r\n  dispatch_async(dispatch_get_main_queue(), ^{\r\n    \r\n    \/\/ Captured inside a block, increacing retain count to 2\r\n    NSLog(@\"A %u\", [object retainCount]); \/\/ 2\r\n    \r\n    dispatch_async(dispatch_get_main_queue(), ^{\r\n      \r\n      \/\/ Captured inside another block, increasing retain count to 3?\r\n      \/\/ but, NO! It is only 2 still\r\n      \/\/ Is this because the blocks are async?\r\n      \/\/ The first block has already completed by the time this\r\n      \/\/ block executes on the next loop?\r\n      \/\/\r\n      \/\/ The answer is that the enclosing block executes,\r\n      \/\/ the current block captures 'object' (retain count now 3)\r\n      \/\/ places this block on the queue, then completes, popping off the stack &\r\n      \/\/ decrementing the retain count back to 2.\r\n      NSLog(@\"B %u\", [object retainCount]); \/\/ 2\r\n      \r\n    });\r\n    \r\n    \/\/ The 2nd block has been dispatched, but not yet executed\r\n    \/\/ initial-retain-count + block-capture + block-capture = 3\r\n    NSLog(@\"C %u\", [object retainCount]); \/\/ 3\r\n    \r\n  });\r\n  \r\n  \/\/ The 1st block has captured 'object', increasing retain count\r\n  \/\/ The 2nd block has not yet captured 'object' because the 1st block has not\r\n  \/\/ executed yet.\r\n  \/\/ initial-retain-count + block-capture = 2\r\n  NSLog(@\"D %u\", [object retainCount]); \/\/ 2\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I have &#8216;come of age&#8217; in the ARC era. Although I have done some manual reference counting and think I understand it, I took a test on my Obj-C skills lately and ran across this puzzle. My answer was the simple, obvious and incorrect choice. To understand it better I created this test project and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,11,10],"tags":[],"class_list":["post-193","post","type-post","status-publish","format-standard","hentry","category-blog","category-code","category-development"],"_links":{"self":[{"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/posts\/193","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/comments?post=193"}],"version-history":[{"count":22,"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/posts\/193\/revisions"}],"predecessor-version":[{"id":352,"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/posts\/193\/revisions\/352"}],"wp:attachment":[{"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/media?parent=193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/categories?post=193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/brian.cordanyoung.com\/Portfolio\/wp-json\/wp\/v2\/tags?post=193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}