<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cocoanetics</title>
	<atom:link href="http://www.cocoanetics.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cocoanetics.com</link>
	<description>Our DNA is written in Objective-C</description>
	<lastBuildDate>Sun, 20 May 2012 14:40:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Twitter.framework Tutorial</title>
		<link>http://www.cocoanetics.com/2012/05/twitter-framework-tutorial/</link>
		<comments>http://www.cocoanetics.com/2012/05/twitter-framework-tutorial/#comments</comments>
		<pubDate>Sun, 20 May 2012 14:40:36 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6356</guid>
		<description><![CDATA[I have this idea for an app that I would totally use myself. You know I started XcodeJobs.com and the @XcodeJobs twitter feed to go with it to have a channel to retweet all the iOS-related job offerings that flow before my very eyes. For the site I&#8217;ve been talking to people to create a login for themselves and post their jobs self-servingly. For the twitter feed I&#8217;ve been using the Twitter search features with a variety of search terms to find tweets where company owners of the developers themselves are tweeting about job postings. Now the reality of the matter is that most of all Tweets are from recruiters, agencies, job sites and other kinds of services that a self-respecting iOS developer does not want anything to do with. So right now I&#8217;m manually filtering tweets. There are a variety of criteria that I want to be able to combine to end up at the real good retweet-worthy tweets. &#160; For example I would do a search for &#8220;hiring iOS&#8221; &#8230; Criteria for exclusion might include: Jack Patrick I found to be a recruiter Jobely.com and Jobrep.com are examples for job websites The jobmakesfun is pointing to a Freelancer site with a ridiculous project description. The one for Viki is pointing to a dubious URL that does not seem to correspond with the hiring company. On the above screenshot the one tweet by Fable Technologies is the only one I deemed worthy of retweeting. It does not contain link bait, is by the guys for themselves, no commercially interested middle man in sight and they are so daring as to even post their e-mail address. All of these manual steps surely can be automated. I&#8217;m envisioning several black lists of twitter accounts that I want to ignore. And the second big category would be to ignore tweets that are leading to job sites (like Bullhorn Reach) or agencies. The user (i.e. myself) could configure multiple elaborate search queries and have the app filter out all the crap. So ideally this would leave us with the true gems of Twitterdom. What Twitter Engine to Use? So I sat down in front of my home iMac and started to think to myself: &#8220;OMG that will be hell of a job. Maybe I should go look for a good Twitter engine to use first.&#8221; The reason for this train of thought was that nowadays most of the interaction with the Twitter REST API has to be authenticated via OAuth. Which is why there are a bunch of OAuth frameworks in the wild, including one from Google because their APIs are OAuth-heavy as well. OAuth basically works by having a secret token that you have to add to all URL requests that need authentication. Of course one could program this from scratch but you&#8217;d certainly spend quite some time on this. Even using a third party OAuth library would not be straightforward because of the time it takes to figure out how to include it in your app. All of these reasons would make this small project unrealistic for a couple of stolen hours on a Sunday. Some people recommended MGTwitterEngine, but then it dawned on me that there was something new that Apple had introduced with iOS 5. So I checked the SDK documentation and &#8211; indeed! &#8211; besides the TWTweetComposeViewController that everybody now knows about there is a second class that is exactly what we need: TWRequest. Tw&#8230;TW&#8230;TWRequest? Hidden behind the simplest of names is a wrapper that you can do any kind of request with. Think of it as a block-based wrapper around NSURLConnection with all the trimmings needed to also do authentication where necessary. Let&#8217;s dive right in, and start by doing a simple search. We added the Twitter.framework to the linked libraries and in the class where we want to call TWRequest we added &#60;Twitter/Twitter.h&#62;. I prefer to put that in the PCH file so that it is available everywhere without needing an extra inclusion of the header. The search itself is deceptively simple: NSURL *searchURL = &#91;NSURL URLWithString:@&#34;http://search.twitter.com/search.json&#34;&#93;; NSDictionary *parameters = &#91;NSDictionary dictionaryWithObject:@&#34;hiring ios&#34; forKey:@&#34;q&#34;&#93;; TWRequest *request = &#91;&#91;TWRequest alloc&#93; initWithURL:searchURL parameters:parameters requestMethod:TWRequestMethodGET&#93;; &#160; &#91;request performRequestWithHandler:^&#40;NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error&#41; &#123; if &#40;responseData&#41; &#123; NSError *parseError = nil; id json = &#91;NSJSONSerialization JSONObjectWithData:responseData options:0 error:&#38;amp;parseError&#93;; &#160; if &#40;!json&#41; &#123; NSLog&#40;@&#34;Parse Error: %@&#34;, parseError&#41;; &#125; else &#123; NSLog&#40;@&#34;%@&#34;, json&#41;; &#125; &#125; else &#123; NSLog&#40;@&#34;Request Error: %@&#34;, &#91;error localizedDescription&#93;&#41;; &#125; &#125;&#93;; To perform a Twitter request you need to have a couple of ingredients, which you can glean from the Twitter API Documentation, for example for the search function. We needed the URL which is a composite of: the so-called endpoint: http://search.twitter.com the method name: search the response data format: json The parameters need to be provided in a dictionary which [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/05/twitter-framework-tutorial/"></g:plusone></div><p>I have this idea for an app that I would totally use myself. You know I started <a href="http://www.xcodejobs.com">XcodeJobs.com</a> and the <a href="http://www.twitter.com/xcodejobs">@XcodeJobs</a> twitter feed to go with it to have a channel to retweet all the iOS-related job offerings that flow before my very eyes. For the site I&#8217;ve been talking to people to create a login for themselves and post their jobs self-servingly. For the twitter feed I&#8217;ve been using the Twitter search features with a variety of search terms to find tweets where company owners of the developers themselves are tweeting about job postings.</p>
<p>Now the reality of the matter is that most of all Tweets are from recruiters, agencies, job sites and other kinds of services that a self-respecting iOS developer does not want anything to do with. So right now I&#8217;m manually filtering tweets. There are a variety of criteria that I want to be able to combine to end up at the real good retweet-worthy tweets.</p>
<p><span id="more-6356"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>For example I would do a search for &#8220;hiring iOS&#8221; &#8230;</p>
<p><a href="http://www.cocoanetics.com/files/AtVBXB2CAAIwn9I.png-large.png"><img class="alignnone  wp-image-6357" title="Filtering Fun" src="http://www.cocoanetics.com/files/AtVBXB2CAAIwn9I.png-large.png" alt="" width="614" height="461" /></a></p>
<p>Criteria for exclusion might include:</p>
<ul>
<li>Jack Patrick I found to be a recruiter</li>
<li>Jobely.com and Jobrep.com are examples for job websites</li>
<li>The jobmakesfun is pointing to a Freelancer site with a ridiculous project description.</li>
<li>The one for Viki is pointing to a dubious URL that does not seem to correspond with the hiring company.</li>
</ul>
<p>On the above screenshot the one tweet by Fable Technologies is the only one I deemed worthy of retweeting. It does not contain link bait, is by the guys for themselves, no commercially interested middle man in sight and they are so daring as to even post their e-mail address.</p>
<p>All of these manual steps surely can be automated. I&#8217;m envisioning several black lists of twitter accounts that I want to ignore. And the second big category would be to ignore tweets that are leading to job sites (like Bullhorn Reach) or agencies. The user (i.e. myself) could configure multiple elaborate search queries and have the app filter out all the crap. So ideally this would leave us with the true gems of Twitterdom.</p>
<h3>What Twitter Engine to Use?</h3>
<p>So I sat down in front of my home iMac and started to think to myself: <em>&#8220;OMG that will be hell of a job. Maybe I should go look for a good Twitter engine to use first.&#8221;</em></p>
<p>The reason for this train of thought was that nowadays most of the interaction with the Twitter REST API has to be authenticated via OAuth. Which is why there are a bunch of OAuth frameworks in the wild, including one from Google because their APIs are OAuth-heavy as well. OAuth basically works by having a secret token that you have to add to all URL requests that need authentication. Of course one could program this from scratch but you&#8217;d certainly spend quite some time on this. Even using a third party OAuth library would not be straightforward because of the time it takes to figure out how to include it in your app.</p>
<p>All of these reasons would make this small project unrealistic for a couple of stolen hours on a Sunday.</p>
<p>Some people recommended MGTwitterEngine, but then it dawned on me that there was something new that Apple had introduced with iOS 5. So I checked the SDK documentation and &#8211; indeed! &#8211; besides the TWTweetComposeViewController that everybody now knows about there is a second class that is exactly what we need: <strong>TWRequest</strong>.</p>
<h3>Tw&#8230;TW&#8230;TWRequest?</h3>
<p>Hidden behind the simplest of names is a wrapper that you can do any kind of request with. Think of it as a block-based wrapper around NSURLConnection with all the trimmings needed to also do authentication where necessary.</p>
<p>Let&#8217;s dive right in, and start by doing a simple search. We added the Twitter.framework to the linked libraries and in the class where we want to call TWRequest we added &lt;Twitter/Twitter.h&gt;. I prefer to put that in the PCH file so that it is available everywhere without needing an extra inclusion of the header.</p>
<p>The search itself is deceptively simple:</p>

<div class="wp_codebox"><table><tr id="p63566"><td class="code" id="p6356code6"><pre class="objc" style="font-family:monospace;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>searchURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> URLWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://search.twitter.com/search.json&quot;</span><span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span>parameters <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;hiring ios&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;q&quot;</span><span style="color: #002200;">&#93;</span>;
TWRequest <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TWRequest alloc<span style="color: #002200;">&#93;</span> initWithURL<span style="color: #002200;">:</span>searchURL parameters<span style="color: #002200;">:</span>parameters requestMethod<span style="color: #002200;">:</span>TWRequestMethodGET<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>request performRequestWithHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> <span style="color: #002200;">*</span>responseData, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/"><span style="color: #400080;">NSHTTPURLResponse</span></a> <span style="color: #002200;">*</span>urlResponse, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>responseData<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>parseError <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
        <span style="color: #a61390;">id</span> json <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSJSONSerialization JSONObjectWithData<span style="color: #002200;">:</span>responseData options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> error<span style="color: #002200;">:&amp;</span>amp;parseError<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>json<span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parse Error: %@&quot;</span>, parseError<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">else</span>
        <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, json<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Request Error: %@&quot;</span>, <span style="color: #002200;">&#91;</span>error localizedDescription<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>To perform a Twitter request you need to have a couple of ingredients, which you can glean from the <a href="https://dev.twitter.com/docs/api">Twitter API Documentation</a>, for example for the <a href="https://dev.twitter.com/docs/api/1/get/search">search</a> function.</p>
<p>We needed the URL which is a composite of:</p>
<ul>
<li>the so-called endpoint: <strong>http://search.twitter.com</strong></li>
<li>the method name: <strong>search</strong></li>
<li>the response data format: <strong>json</strong></li>
</ul>
<p>The parameters need to be provided in a dictionary which is also straightforward, the keys are the parameter names and the values are the parameter values. Also we don&#8217;t need authentication for search, in fact it is not even supported according to the Twitter docs. This is to make it impossible for Twitter to track you based on what you search for&#8230; unlike Google.</p>
<p>TWRequests supports the three HTTP verbs GET, POST and DELETE. The documentation tells you which one to use. Note that different API functions might have different end points.</p>
<p>We could have also chosen xml format for the response format, but there is no simple way to transform that into something useful for us. NSXMLParser works event-based and we would have to do some work to get it into a structure. The second ingredient that we need is also new with iOS 5, Apple provides a handy high performance class to serialize and deserialize JSON data.By passing the responds of the TWRequest into <strong>NSJSONSerialization</strong> we get an NSDictionary containing the parsed JSON. With JSON and the de-serialization method provided we get a dictionary which is way more convenient.</p>
<p>If the deserialization worked you get a non-nil result, looking like this:</p>

<div class="wp_codebox"><table><tr id="p63567"><td class="code" id="p6356code7"><pre class="json" style="font-family:monospace;">{
    &quot;completed_in&quot; = &quot;0.027&quot;;
    &quot;max_id&quot; = 204150933297446912;
    &quot;max_id_str&quot; = 204150933297446912;
    &quot;next_page&quot; = &quot;?page=2&amp;amp;max_id=204150933297446912&amp;amp;q=hiring%20ios&quot;;
    page = 1;
    query = &quot;hiring+ios&quot;;
    &quot;refresh_url&quot; = &quot;?since_id=204150933297446912&amp;amp;q=hiring%20ios&quot;;
    results =     (
                {
            &quot;created_at&quot; = &quot;Sun, 20 May 2012 10:05:50 +0000&quot;;
            &quot;from_user&quot; = &quot;fun_programming&quot;;
            &quot;from_user_id&quot; = 282845320;
            &quot;from_user_id_str&quot; = 282845320;
            &quot;from_user_name&quot; = jobmakesfun;
            geo = &quot;&quot;;
            id = 204150933297446912;
            &quot;id_str&quot; = 204150933297446912;
            &quot;iso_language_code&quot; = en;
            metadata =             {
                &quot;result_type&quot; = recent;
            };
            &quot;profile_image_url&quot; = &quot;http://a0.twimg.com/profile_images/1313148959/jobs_normal.gif&quot;;
            &quot;profile_image_url_https&quot; = &quot;https://si0.twimg.com/profile_images/1313148959/jobs_normal.gif&quot;;
            source = &quot;&amp;lt;a href=&quot;http://twitterfeed.com&quot; rel=&quot;nofollow&quot;&amp;gt;twitterfeed&amp;lt;/a&amp;gt;&quot;;
            text = &quot;#ipad #project iOS Game Side Scrolling Battle by olimoli123: I require someone to make a game like ... http://t.co/LNqWsmLs #dev #hiring&quot;;
            &quot;to_user&quot; = &quot;&quot;;
            &quot;to_user_id&quot; = 0;
            &quot;to_user_id_str&quot; = 0;
            &quot;to_user_name&quot; = &quot;&quot;;
        },
                {
            &quot;created_at&quot; = &quot;Sun, 20 May 2012 08:18:14 +0000&quot;;
            &quot;from_user&quot; = XcodeJobs;
            &quot;from_user_id&quot; = 539747758;
            &quot;from_user_id_str&quot; = 539747758;
            &quot;from_user_name&quot; = &quot;Xcode Jobs&quot;;
            geo = &quot;&quot;;
            id = 204123856812785665;
            &quot;id_str&quot; = 204123856812785665;
            &quot;iso_language_code&quot; = pl;
            metadata =             {
                &quot;result_type&quot; = recent;
            };
            &quot;profile_image_url&quot; = &quot;http://a0.twimg.com/profile_images/1988345754/xcode-twitter_normal.png&quot;;
            &quot;profile_image_url_https&quot; = &quot;https://si0.twimg.com/profile_images/1988345754/xcode-twitter_normal.png&quot;;
            source = &quot;&amp;lt;a href=&quot;http://angel.co&quot; rel=&quot;nofollow&quot;&amp;gt;AngelList&amp;lt;/a&amp;gt;&quot;;
            text = &quot;RT @CardFlick: CardFlick (@CardFlick) is hiring a iOS Engineer http://t.co/O7Wf0gtw&quot;;
            &quot;to_user&quot; = &quot;&quot;;
            &quot;to_user_id&quot; = 0;
            &quot;to_user_id_str&quot; = 0;
            &quot;to_user_name&quot; = &quot;&quot;;
        },...</pre></td></tr></table></div>

<p>We get the tweets in an NSArray below the &#8220;results&#8221; key, each tweet being represented by an NSDictionary. If we wanted to refresh the contents of this query we could use the value stated in &#8220;refresh_url&#8221;. Then we would only see tweets that were made after the ones we had already gotten here.</p>
<p>Also results are paginated. To retrieve subsequent pages there is a &#8220;next_page&#8221; value that would get us those. The default is to return 15 tweets per &#8220;page&#8221;. We could easily also increase this number by passing it as the optional &#8220;rpp&#8221; (results per page) parameter.</p>
<h3>Later the same day &#8230;</h3>
<p>I&#8217;m skipping over the part where I&#8217;m merging the result dictionary into a CoreData database and using an NSFetchedResultsController to display the tweets. That is a different story which I shall treat another day. Let&#8217;s just say, I got it to display in a very basic form and pushing a refresh button would redo the same query and merge the results into a database.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-20-um-14.20.31.png"><img class="alignnone size-full wp-image-6360" title="Simple Twitter DB" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-20-um-14.20.31.png" alt="" width="380" height="241" /></a></p>
<p>After getting all the basics wired up (CoreData Stack, methods to query by ID for user and message, merging function, table view controller, fetched results controller) I ended up with a view like this:</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-20-um-14.25.20.png"><img class="alignnone  wp-image-6361" title="Basic Twitter UI" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-20-um-14.25.20.png" alt="" width="238" height="446" /></a></p>
<p>It is immediately apparent from this that we are seeing only tweets that we want to get rid of. 4 of these Twitter accounts would be blacklisted because of the reasons stated above. Also my own tweets are visible as they came from my own account and start with RT, those where the job tweets I had retweeted. OMG the amount of time this tool will save me not having to visually scan through all of this&#8230;</p>
<p>But like every TV cook I&#8217;ve already prepared this step as the details are of no interest for this tutorial. I added a long press gesture recognizer to each cell and a red &#8220;Blacklist&#8221; button that allows me to mark the TwitterUser as blacklisted and remove his tweets from the database. This results in a tremendous improvement.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-20-um-15.03.47.png"><img class="alignnone  wp-image-6363" title="Basic Twitter UI, now cleaned up" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-20-um-15.03.47.png" alt="" width="238" height="446" /></a></p>
<p>Oh, look! Fable Technologies is at the top after having blacklisted all the clutter. They should pay me a referral fee for all this free advertising!</p>
<p>Now for the hard part of this tutorial. Now that we have leaned up the result, we also want to be able to retweet individual messages and of course somehow know if we have done so already to prevent a double-retweeting. Unfortunately there does not seem to be an easy we to get the retweet info included in the search results.</p>
<h3>Dealing with Accounts</h3>
<p>In order to do something that requires authentication we need to ask the global account store for a list of Twitter accounts and have the user pick one. First we add the Accounts.framework in our build phases. Then we add &lt;Accounts/Accounts.h&gt; to our PCH file.</p>
<p>The first time we want access to a given account type (as of iOS 5 only Twitter is supported) we need to ask the user&#8217;s permission. Subsequently we can query the ACAccountType if permission has already been given.</p>

<div class="wp_codebox"><table><tr id="p63568"><td class="code" id="p6356code8"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>account<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIBarButtonItem <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>sender
<span style="color: #002200;">&#123;</span>
    ACAccountStore <span style="color: #002200;">*</span>accountStore <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>ACAccountStore alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    ACAccountType <span style="color: #002200;">*</span>accountType <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>accountStore accountTypeWithAccountTypeIdentifier<span style="color: #002200;">:</span>ACAccountTypeIdentifierTwitter<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>accountType accessGranted<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// have access already</span>
        <span style="color: #002200;">&#91;</span>self _showListOfTwitterAccountsFromStore<span style="color: #002200;">:</span>accountStore<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// need access first</span>
        <span style="color: #002200;">&#91;</span>accountStore requestAccessToAccountsWithType<span style="color: #002200;">:</span>accountType withCompletionHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> granted, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>granted<span style="color: #002200;">&#41;</span>
            <span style="color: #002200;">&#123;</span>
                <span style="color: #002200;">&#91;</span>self _showListOfTwitterAccountsFromStore<span style="color: #002200;">:</span>accountStore<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
            <span style="color: #a61390;">else</span>
            <span style="color: #002200;">&#123;</span>
                UIAlertView <span style="color: #002200;">*</span>alert <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Error&quot;</span> message<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cannot link account without permission&quot;</span> delegate<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Ok&quot;</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
                <span style="color: #002200;">&#91;</span>alert show<span style="color: #002200;">&#93;</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>There is no shared instance of the ACAccountStore, so we have to create our own with alloc/init. Then we create the ACAccountType for Twitter and check if we might already have access granted. If not then we ask for it passing a completion handler. For sake of simplicity I opted to just show an action sheet for all the configured accounts. This does not deal with the situation of no configured accounts.</p>

<div class="wp_codebox"><table><tr id="p63569"><td class="code" id="p6356code9"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>_showListOfTwitterAccountsFromStore<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>ACAccountStore <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>accountStore
<span style="color: #002200;">&#123;</span>
    ACAccountType <span style="color: #002200;">*</span>accountType <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>accountStore accountTypeWithAccountTypeIdentifier<span style="color: #002200;">:</span>ACAccountTypeIdentifierTwitter<span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>twitterAccounts <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>accountStore accountsWithAccountType<span style="color: #002200;">:</span>accountType<span style="color: #002200;">&#93;</span>;
&nbsp;
    UIActionSheet <span style="color: #002200;">*</span>actions <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIActionSheet alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Choose Account to Use&quot;</span> delegate<span style="color: #002200;">:</span>self cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Cancel&quot;</span> destructiveButtonTitle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> otherButtonTitles<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    actions.tag <span style="color: #002200;">=</span> <span style="color: #2400d9;">2</span>;
&nbsp;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>shownAccounts <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>ACAccount <span style="color: #002200;">*</span>oneAccount <span style="color: #a61390;">in</span> twitterAccounts<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>actions addButtonWithTitle<span style="color: #002200;">:</span>oneAccount.username<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>shownAccounts addObject<span style="color: #002200;">:</span>oneAccount<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    _shownAccounts <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>shownAccounts copy<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>actions showInView<span style="color: #002200;">:</span>self.view<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Since I don&#8217;t have any block-based action sheet handy I need to remember the list of accounts presented in _shownAccounts IVAR and then in the delegate method for the action sheet I can pick the correct one based on the index. The important thing here is that we end up with an instance of a ACAccount.</p>
<h3>Now Let&#8217;s Sign This&#8230;</h3>
<p>Let&#8217;s quickly check the <a href="https://dev.twitter.com/docs/api/1/post/statuses/retweet/%3Aid">Retweet API </a>and what we need to perform such a request.</p>
<p>Just like above for the search we need to construct a URL from these parts:</p>
<ul>
<li>the endpoint: <strong>http://api.twitter.com/1</strong></li>
<li>the method name: <strong>statuses/retweet</strong></li>
<li>the identifier of the tweet to retweet:<strong> some number</strong></li>
<li>the response data format: <strong>json</strong></li>
<li>no parameters necessary</li>
</ul>
<p>Here I stumbled across something that was not immediately obvious to me. You have to store the ACAccountStore in an instance variable. Otherwise the ACAccount&#8217;s ACAccountType will be released by the autorelease pool. At let&#8217;s that&#8217;s what happened to me, I got a memory exception and an authentication error in alternation. Could it be that there&#8217;s a bug in the Accounts framework? Seems to me that the accountType property of ACAccount should be a strong reference, but it isn&#8217;t.</p>
<p>But that aside, there&#8217;s no hurt making an IVAR for the account store, the function to retweet would then look like this:</p>

<div class="wp_codebox"><table><tr id="p635610"><td class="code" id="p6356code10"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>_retweetMessage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>TwitterMessage <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>message
<span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>retweetString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://api.twitter.com/1/statuses/retweet/%@.json&quot;</span>, message.identifier<span style="color: #002200;">&#93;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>retweetURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> URLWithString<span style="color: #002200;">:</span>retweetString<span style="color: #002200;">&#93;</span>;
    TWRequest <span style="color: #002200;">*</span>request <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TWRequest alloc<span style="color: #002200;">&#93;</span> initWithURL<span style="color: #002200;">:</span>retweetURL parameters<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> requestMethod<span style="color: #002200;">:</span>TWRequestMethodPOST<span style="color: #002200;">&#93;</span>;
    request.account <span style="color: #002200;">=</span> _usedAccount;
&nbsp;
    <span style="color: #002200;">&#91;</span>request performRequestWithHandler<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> <span style="color: #002200;">*</span>responseData, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/"><span style="color: #400080;">NSHTTPURLResponse</span></a> <span style="color: #002200;">*</span>urlResponse, <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>error<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>responseData<span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#123;</span>
            <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>parseError <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
            <span style="color: #a61390;">id</span> json <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>NSJSONSerialization JSONObjectWithData<span style="color: #002200;">:</span>responseData options<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span> error<span style="color: #002200;">:&amp;</span>amp;parseError<span style="color: #002200;">&#93;</span>;
&nbsp;
            <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>json<span style="color: #002200;">&#41;</span>
            <span style="color: #002200;">&#123;</span>
                NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Parse Error: %@&quot;</span>, parseError<span style="color: #002200;">&#41;</span>;
            <span style="color: #002200;">&#125;</span>
            <span style="color: #a61390;">else</span>
            <span style="color: #002200;">&#123;</span>
                NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@&quot;</span>, json<span style="color: #002200;">&#41;</span>;
            <span style="color: #002200;">&#125;</span>
        <span style="color: #002200;">&#125;</span>
        <span style="color: #a61390;">else</span>
        <span style="color: #002200;">&#123;</span>
            NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Request Error: %@&quot;</span>, <span style="color: #002200;">&#91;</span>error localizedDescription<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>There are three differences here versus the search request. 1) this one is a POST, 2) there are no parameters and 3) we set the account property to the ACAccount we have selected earlier. And if this works we indeed see the retweets show up immediately.</p>
<p><a href="http://www.cocoanetics.com/files/AtWHHvPCQAAtm6u.png-large.png"><img class="alignnone  wp-image-6366" title="Tweets showing up" src="http://www.cocoanetics.com/files/AtWHHvPCQAAtm6u.png-large.png" alt="" width="614" height="461" /></a></p>
<p>If you get an authentication error, then there&#8217;s a problem with the ACAccount. If you get some error complaining that this cannot be done with the given tweet, then most likely you have already retweeted it before. And in case of success you get a response with some retweet status.</p>
<h3>Conclusion</h3>
<p>There are a couple more touches necessary to make this app really useful. For one, we also need to retrieve the timeline of own retweets to be able to mark the tweets we already looked at. Also the retweet response should somehow be used to mark the tweet as retweeted.</p>
<p>And of course the UI could use much more work. We want to asynchronously show the profile pictures, access and edit the blacklist, decode the shortened URLs and make a blacklist based on those and of course be able to specify multiple search query for a given topic. For the UI I&#8217;ll probably use my DTCoreText method that lets me render the tweets with interactive hyperlinks.</p>
<p>But the gist of this post is that if you know about the Twitter and the Account frameworks then it is quite easy to build your own specialized Twitter client. We can extend a heart-felt &#8220;Thank You!&#8221; to the engineers at Apple who built something as useful as these into the operating system. Interacting with Twitter couldn&#8217;t be easier!</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6356&amp;md5=22829170047a27b41eabfd4044e3bf83" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/05/twitter-framework-tutorial/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F05%2Ftwitter-framework-tutorial%2F&amp;language=en_GB&amp;category=text&amp;title=Twitter.framework+Tutorial&amp;description=I+have+this+idea+for+an+app+that+I+would+totally+use+myself.+You+know+I+started+XcodeJobs.com+and+the+%40XcodeJobs+twitter+feed+to+go+with+it+to+have+a...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Podcast #37 &#8211; &#8220;WWDC Scholarship&#8221;</title>
		<link>http://www.cocoanetics.com/2012/05/podcast-37-wwdc-scholarship/</link>
		<comments>http://www.cocoanetics.com/2012/05/podcast-37-wwdc-scholarship/#comments</comments>
		<pubDate>Fri, 18 May 2012 20:42:54 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6352</guid>
		<description><![CDATA[My guest Paul Dunahoo won one of 150 Apple WWDC Student scholarships. We talk about what he did to win it, some hopes for iOS 6 and I share some of my tips for how to make your first WWDC more enjoyable. &#160; Interview Paul Dunahoo, 13. From Connecticut. Homepage PADGuy1 on Twitter Note Taking App Scrawl on App Store WWDC Scholarships Official Rules PS: Right after we recorded the show he got a phone call from Apple. &#8220;Parents can go, but not to the keynote or sessions&#8221;.]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/05/podcast-37-wwdc-scholarship/"></g:plusone></div><p>My guest Paul Dunahoo won one of 150 Apple WWDC Student scholarships. We talk about what he did to win it, some hopes for iOS 6 and I share some of my tips for how to make your first WWDC more enjoyable.</p>

<p><span id="more-6352"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>Interview</h3>
<p>Paul Dunahoo, 13. From Connecticut.</p>
<ul>
<li><a href="http://allendunahoo.com/">Homepage</a></li>
<li><a href="http://www.twitter.com/PADGuy1">PADGuy1</a> on Twitter</li>
<li>Note Taking App <a href="http://itunes.apple.com/us/app/scrawl/id480126603?ls=1&amp;mt=12">Scrawl</a> on App Store</li>
<li><a href="https://developer.apple.com/wwdc/scholarships/">WWDC Scholarships Official Rules</a></li>
</ul>
<p>PS: Right after we recorded the show he got a phone call from Apple. &#8220;Parents can go, but not to the keynote or sessions&#8221;.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6352&amp;md5=d064c44756c7de833eba5fde4d51c470" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/05/podcast-37-wwdc-scholarship/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.cocoanetics.com/files/Cocoanetics_037.mp3" length="63331524" type="audio/mpeg" />
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F05%2Fpodcast-37-wwdc-scholarship%2F&amp;language=en_GB&amp;category=text&amp;title=Podcast+%2337+%26%238211%3B+%26%238220%3BWWDC+Scholarship%26%238221%3B&amp;description=My+guest+Paul+Dunahoo+won+one+of+150+Apple+WWDC+Student+scholarships.+We+talk+about+what+he+did+to+win+it%2C+some+hopes+for+iOS+6+and+I+share+some...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Weird ARC error And The Invisible Header</title>
		<link>http://www.cocoanetics.com/2012/05/weird-arc-error-and-the-invisible-header/</link>
		<comments>http://www.cocoanetics.com/2012/05/weird-arc-error-and-the-invisible-header/#comments</comments>
		<pubDate>Mon, 07 May 2012 17:44:55 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Bug Reports]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6344</guid>
		<description><![CDATA[There&#8217;s a bug &#8211; it seems &#8211; in Xcode 4.3.2 that was causing an issue with my DTBannerManager component. I&#8217;m documenting the workaround here and how to recognize that you are experiencing the bug. &#160; DTBannerManger &#8211; a component to unite iAds, MobFox and Google AdMob &#8211; has a subfolder Externals that contains a clone of the MobFox iOS SDK from GitHub. Since the component only links in the Static Library product of the MobFox Xcode project this is the only file that I had added to my project. No use in adding any other superfluous files, right? The first symptom of the issue was that you would get a weird ARC-related Warning: &#8220;Sending DTBannerManager *const __strong&#8221; to parameter of incompatible type &#8220;id &#60;MobFoxBannerViewDelegate&#62;&#8221; Well, what do we do if we get a warning on a setDelegate:self? We check the header to see if the class is defined to comply with the protocol. There I found that the &#60;MobFoxBannerViewDelegate&#62; protocol declaration was missing. So we added that plus the import for the header where this protocol is defined. Here&#8217;s a bit of a WTF. Why does it not find the header? So next I went and checked the search path for the headers. I was pretty sure that this was working as of Xcode 4.3. The header search path is in the build settings: This is set up correctly. The path from the project root is Core/Externals and the double asterisks mean that it should be searching recursively. And as I said before, this was working perfectly before. The workaround is quite simple, but it&#8217;s not obvious. I only found it out myself after messing around for over an hour with a client who was having the same issue setting up my DTRichTextEditor as sub-project in one of his apps. You need to add the header that cannot be found to the project, even though it is not associated with any targets. Apparently this is necessary for the Xcode indexer to be able to &#8220;see&#8221; the header. That&#8217;s all it takes. I hope you remember reading about this workaround if you ever happen to stumble across this Xcode bug. I did so twice so far.]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/05/weird-arc-error-and-the-invisible-header/"></g:plusone></div><p>There&#8217;s a bug &#8211; it seems &#8211; in Xcode 4.3.2 that was causing an issue with my <a href="http://www.cocoanetics.com/2010/08/dtbannermanager/">DTBannerManager</a> component. I&#8217;m documenting the workaround here and how to recognize that you are experiencing the bug.</p>
<p><span id="more-6344"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>DTBannerManger &#8211; a component to unite iAds, MobFox and Google AdMob &#8211; has a subfolder Externals that contains a clone of the <a href="https://github.com/mobfox/MobFox-iOS-SDK">MobFox iOS SDK from GitHub</a>. Since the component only links in the Static Library product of the MobFox Xcode project this is the only file that I had added to my project. No use in adding any other superfluous files, right?</p>
<p>The first symptom of the issue was that you would get a weird ARC-related Warning: &#8220;Sending DTBannerManager *const __strong&#8221; to parameter of incompatible type &#8220;id &lt;MobFoxBannerViewDelegate&gt;&#8221;</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.26.46.png"><img class="alignnone  wp-image-6345" title="Weird ARC error" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.26.46.png" alt="" width="625" height="142" /></a></p>
<p>Well, what do we do if we get a warning on a setDelegate:self? We check the header to see if the class is defined to comply with the protocol. There I found that the &lt;MobFoxBannerViewDelegate&gt; protocol declaration was missing. So we added that plus the import for the header where this protocol is defined.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.30.55.png"><img class="alignnone  wp-image-6346" title="Bildschirmfoto 2012-05-07 um 19.30.55" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.30.55.png" alt="" width="646" height="412" /></a></p>
<p>Here&#8217;s a bit of a WTF. Why does it <a title="Helping Xcode Find Library Headers" href="http://www.cocoanetics.com/2012/01/helping-xcode-find-library-headers/">not find the header</a>?</p>
<p>So next I went and checked the search path for the headers. I was pretty sure that this was working as of Xcode 4.3. The header search path is in the build settings:</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.36.35.png"><img class="alignnone  wp-image-6347" title="Header Search Paths" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.36.35.png" alt="" width="648" height="166" /></a></p>
<p>This is set up correctly. The path from the project root is Core/Externals and the double asterisks mean that it should be searching recursively. And as I said before, this was working perfectly before.</p>
<p>The workaround is quite simple, but it&#8217;s not obvious. I only found it out myself after messing around for over an hour with a client who was having the same issue setting up my <a href="http://www.cocoanetics.com/parts/dtrichtexteditor/">DTRichTextEditor</a> as sub-project in one of his apps.</p>
<p>You need to add the header that cannot be found to the project, even though it is not associated with any targets. Apparently this is necessary for the Xcode indexer to be able to &#8220;see&#8221; the header.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.40.14.png"><img class="alignnone  wp-image-6348" title="Adding the header so that it is visible" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-07-um-19.40.14.png" alt="" width="262" height="255" /></a></p>
<p>That&#8217;s all it takes. I hope you remember reading about this workaround if you ever happen to stumble across this Xcode bug. I did so twice so far.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6344&amp;md5=82d02e2ca8577a34d8b3cf4be627aaae" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/05/weird-arc-error-and-the-invisible-header/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F05%2Fweird-arc-error-and-the-invisible-header%2F&amp;language=en_GB&amp;category=text&amp;title=Weird+ARC+error+And+The+Invisible+Header&amp;description=There%26%238217%3Bs+a+bug+%26%238211%3B+it+seems+%26%238211%3B+in+Xcode+4.3.2+that+was+causing+an+issue+with+my+DTBannerManager+component.+I%26%238217%3Bm+documenting+the+workaround+here+and+how+to+recognize+that+you...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Podcast #36 &#8211; &#8220;Google Currents&#8221;</title>
		<link>http://www.cocoanetics.com/2012/05/podcast-36-google-currents/</link>
		<comments>http://www.cocoanetics.com/2012/05/podcast-36-google-currents/#comments</comments>
		<pubDate>Sun, 06 May 2012 21:26:07 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6336</guid>
		<description><![CDATA[Episode 36, recorded Sunday May 6th, 2012 In this episode my special guest is Will Kiefer. He is the Senior iOS Engineer in charge of Google Currents. Will tells us why UIWebView isn&#8217;t all that bad and has some amazing performance tips for us with which to tame it. You should make lots of notes and you will feel like you visited a lab at WWDC and had your brain supercharged. &#160; Show Notes Google Currents iOS app on the app store, recently available internationally. Performance Notes: Cache UIWebViews, saves time on setup When profiling also look at CoreAnimation tool and VM tracker JavaScript is slow (e.g. JQuery), because JIT compiler is not available for web views Avoid changing the frame of web views, that causes it to do overtime When communicating from web view to Objective-C it is faster to change the hash on a small hidden iframe The frame of a web view should be smaller than the size of the screen, or if that is not possible have a clipping view NSURLProtocol is a better choice for caching than NSURLCache because it is concurrent With CoreData Will has one MOC for UI stuff and a second for updating in background, changes are then merged in by UI MOC Google Currents Producer Tool, requires Chrome at present. Will Kiefer on Twitter, on Google+]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/05/podcast-36-google-currents/"></g:plusone></div><p>Episode 36, recorded Sunday May 6th, 2012</p>
<p>In this episode my special guest is <strong>Will Kiefer</strong>. He is the Senior iOS Engineer in charge of <strong>Google Currents</strong>. Will tells us why UIWebView isn&#8217;t all that bad and has some amazing performance tips for us with which to tame it. You should make lots of notes and you will feel like you visited a lab at WWDC and had your brain supercharged.</p>

<p><span id="more-6336"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>Show Notes</h3>
<p>Google Currents iOS app <a href="http://itunes.apple.com/at/app/google-currents/id459182288?mt=8">on the app store</a>, recently available internationally.</p>
<p>Performance Notes:</p>
<ul>
<li>Cache UIWebViews, saves time on setup</li>
<li>When profiling also look at CoreAnimation tool and VM tracker</li>
<li>JavaScript is slow (e.g. JQuery), because JIT compiler is not available for web views</li>
<li>Avoid changing the frame of web views, that causes it to do overtime</li>
<li>When communicating from web view to Objective-C it is faster to change the hash on a small hidden iframe</li>
<li>The frame of a web view should be smaller than the size of the screen, or if that is not possible have a clipping view</li>
<li>NSURLProtocol is a better choice for caching than NSURLCache because it is concurrent</li>
<li>With CoreData Will has one MOC for UI stuff and a second for updating in background, changes are then merged in by UI MOC</li>
</ul>
<p>Google Currents <a href="http://producer.google.com">Producer</a> Tool, requires Chrome at present.</p>
<p>Will Kiefer <a href="http://twitter.com/#!/wkiefer">on Twitter</a>, on <a href="https://plus.google.com/114617554755271805426">Google+</a></p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6336&amp;md5=a4e2aebdd7398dc3839dc7d57ae8f871" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/05/podcast-36-google-currents/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.cocoanetics.com/files/Cocoanetics_036.mp3" length="64471731" type="audio/mpeg" />
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F05%2Fpodcast-36-google-currents%2F&amp;language=en_GB&amp;category=text&amp;title=Podcast+%2336+%26%238211%3B+%26%238220%3BGoogle+Currents%26%238221%3B&amp;description=Episode+36%2C+recorded+Sunday+May+6th%2C+2012+In+this+episode+my+special+guest+is+Will+Kiefer.+He+is+the+Senior+iOS+Engineer+in+charge+of+Google+Currents.+Will+tells+us...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>GCD, ARC, Blocks &#8211; Oh How Simple!</title>
		<link>http://www.cocoanetics.com/2012/05/gcd-arc-blocks-oh-how-simple/</link>
		<comments>http://www.cocoanetics.com/2012/05/gcd-arc-blocks-oh-how-simple/#comments</comments>
		<pubDate>Sat, 05 May 2012 16:32:42 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6327</guid>
		<description><![CDATA[I&#8217;m &#8220;totally&#8221; migrating my iCatalog framework project to ARC, GCD and blocks and I&#8217;d like to share with you some of the revelations that the use of these modern technologies brings with them. Here are two examples of the kind of simplifications you will see if you do the same. This approach is compatible with iOS 4.0 and above. &#160; Executing a Multi-Parameter Method on Main Thread I was looking for instances of performSelectorOnMainThread so that I could replace them with a dispatch_sync on main_queue instead. Previously when calling methods that take more than one parameter you had to jump through hoops. Before: - &#40;void&#41;reportAddProduct:&#40;Product *&#41;product toBagAs:&#40;BagItem*&#41;bagItem &#123; SEL selector = @selector&#40;onlineIntegrationManager:willAddProduct:toBagAs:&#41;; if &#40;&#91;delegate respondsToSelector:selector&#93;&#41; &#123; NSMethodSignature *signature = &#91;self methodSignatureForSelector:selector&#93;; if &#40;!signature&#41; &#123; return; &#125; &#160; NSInvocation* invocation = &#91;NSInvocation invocationWithMethodSignature:signature&#93;; &#91;invocation setTarget:delegate&#93;; &#91;invocation setSelector:selector&#93;; &#91;invocation setArgument:&#38;product atIndex:2&#93;; &#91;invocation setArgument:&#38;bagItem atIndex:3&#93;; &#91;invocation retainArguments&#93;; &#91;invocation performSelectorOnMainThread:@selector&#40;invoke&#41; withObject:nil waitUntilDone:YES&#93;; &#125; &#125; After: - &#40;void&#41;reportAddProduct:&#40;Product *&#41;product toBagAs:&#40;BagItem *&#41;bagItem &#123; if &#40;&#91;delegate respondsToSelector:@selector&#40;onlineIntegrationManager:willAddProduct:toBagAs:&#41;&#93;&#41; &#123; dispatch_sync&#40;dispatch_get_main_queue&#40;&#41;, ^&#123; &#91;delegate onlineIntegrationManager:self willAddProduct:product toBagAs:bagItem&#93;; &#125;&#41;; &#125; &#125; The handy dispatch_sync on main queue can call any method, with any number of parameters on the main thread. The sync is equivalent to the waitUntilDone:YES. Since this allows for putting the main thread code inline you no longer need to have special methods that you then performSelectorOnMainThread:. As a second note I found that it calls to the main thread should generally be done synchronously because I had a situation where a UILabel would not get updated if I did waitUntilDone:NO. Having everything as dispatch_sync now also takes care of that. Abusing the UIView Animation Context Before we had block based animation I would find myself often passing some context to the animationDidStopSelector so that I can do some wrap-up work when the animation is done. This is quite unsafe, even ARC complains about that unless you add a (__bridge id) to tell it to ignore the memory management of this object. Context parameters didn&#8217;t get retained as a rule of thumb. In this example I needed to remove a view that has been animated out also from an internal dictionary after it was done. Having a dedicated instance variable would not have been an option because you could potentially have multiple animations going on at the same time. Before: - &#40;void&#41;removalAnimationDidStop:&#40;NSString *&#41;animationID finished:&#40;NSNumber *&#41;finished context:&#40;void *&#41;context &#123; UIView *removedView = &#40;__bridge UIView *&#41;context; &#160; for &#40;NSNumber *oneKey in &#91;self.viewsForItems allKeys&#93;&#41; &#123; UIView *view = &#91;self.viewsForItems objectForKey:oneKey&#93;; &#160; if &#40;view == removedView&#41; &#123; &#91;removedView removeFromSuperview&#93;; &#91;self.viewsForItems removeObjectForKey:oneKey&#93;; &#125; &#125; &#125; &#160; // the above being called by: &#160; for &#40;id oneItem in itemsToRemove&#41; &#123; // we must have a view for this item to remove it __unsafe_unretained UIView *itemView = &#91;self viewForItem:oneItem&#93;; &#160; if &#40;animated&#41; &#123; &#91;UIView beginAnimations:@&#34;ItemRemoval&#34; context:&#40;__bridge void *&#41;itemView&#93;; &#91;UIView setAnimationDuration:deleteAnimationDuration&#93;; if &#40;delaySoFar&#62;0&#41; &#123; &#91;UIView setAnimationDelay:delaySoFar&#93;; &#125; &#91;UIView setAnimationBeginsFromCurrentState:YES&#93;; &#91;UIView setAnimationDidStopSelector:@selector&#40;removalAnimationDidStop:finished:context:&#41;&#93;; &#91;UIView setAnimationDelegate:self&#93;; &#125; &#160; itemView.alpha = 0; itemView.transform =CGAffineTransformMakeScale&#40;0.5, 0.5&#41;; &#160; if &#40;animated&#41; &#123; &#91;UIView commitAnimations&#93;; &#125; &#160; delaySoFar +=deleteAnimationOffset; &#125; After: // moved into a convenience method - &#40;void&#41;removeCachedView:&#40;UIView *&#41;removedView &#123; for &#40;NSNumber *oneKey in &#91;self.viewsForItems allKeys&#93;&#41; &#123; UIView *view = &#91;self.viewsForItems objectForKey:oneKey&#93;; &#160; if &#40;view == removedView&#41; &#123; &#91;removedView removeFromSuperview&#93;; &#91;self.viewsForItems removeObjectForKey:oneKey&#93;; &#125; &#125; &#125; &#160; // called from: &#160; for &#40;id oneItem in itemsToRemove&#41; &#123; // we must have a view for this item to remove it __unsafe_unretained UIView *itemView = &#91;self viewForItem:oneItem&#93;; &#160; &#91;UIView animateWithDuration:&#40;animated?deleteAnimationDuration:0&#41; delay:&#40;animated?delaySoFar:0&#41; options:UIViewAnimationOptionBeginFromCurrentState animations:^&#123; itemView.alpha = 0; itemView.transform =CGAffineTransformMakeScale&#40;0.5, 0.5&#41;; &#125; completion:^&#40;BOOL finished&#41; &#123; &#91;self removeCachedView:itemView&#93;; &#125;&#93;; &#160; delaySoFar +=deleteAnimationOffset; &#125; A boolean animated value can easily be replaced with a duration of 0. Animation delays are passed in the appropriate method and the beginsFromCurrentState is now a UIViewAnimationOption. This method is way safer because the blocks &#8220;capture&#8221; (i.e.) retain all the used variables making it impossible for the thing that was previously passed via the context to already been deallocated. Conclusion Sorry for not having more wise words to add here. The beauty of the possible simplifications you get if you decide to make iOS 4 your minimum deployment target should speak for itself.]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/05/gcd-arc-blocks-oh-how-simple/"></g:plusone></div><p>I&#8217;m &#8220;totally&#8221; migrating my iCatalog framework project to ARC, GCD and blocks and I&#8217;d like to share with you some of the revelations that the use of these modern technologies brings with them.</p>
<p>Here are two examples of the kind of simplifications you will see if you do the same. This approach is compatible with iOS 4.0 and above.</p>
<p><span id="more-6327"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>Executing a Multi-Parameter Method on Main Thread</h3>
<p>I was looking for instances of performSelectorOnMainThread so that I could replace them with a dispatch_sync on main_queue instead. Previously when calling methods that take more than one parameter you had to jump through hoops.  </p>
<p><strong>Before:</strong></p>

<div class="wp_codebox"><table><tr id="p632720"><td class="code" id="p6327code20"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>reportAddProduct<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>Product <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>product toBagAs<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>BagItem<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>bagItem
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">SEL</span> selector <span style="color: #002200;">=</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>onlineIntegrationManager<span style="color: #002200;">:</span>willAddProduct<span style="color: #002200;">:</span>toBagAs<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>delegate respondsToSelector<span style="color: #002200;">:</span>selector<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMethodSignature_Class/"><span style="color: #400080;">NSMethodSignature</span></a> <span style="color: #002200;">*</span>signature <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self methodSignatureForSelector<span style="color: #002200;">:</span>selector<span style="color: #002200;">&#93;</span>;
		<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>signature<span style="color: #002200;">&#41;</span> 
		<span style="color: #002200;">&#123;</span>
			<span style="color: #a61390;">return</span>;	
		<span style="color: #002200;">&#125;</span>
&nbsp;
		<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/"><span style="color: #400080;">NSInvocation</span></a><span style="color: #002200;">*</span> invocation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/"><span style="color: #400080;">NSInvocation</span></a> invocationWithMethodSignature<span style="color: #002200;">:</span>signature<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>invocation setTarget<span style="color: #002200;">:</span>delegate<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>invocation setSelector<span style="color: #002200;">:</span>selector<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>invocation setArgument<span style="color: #002200;">:&amp;</span>product atIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>invocation setArgument<span style="color: #002200;">:&amp;</span>bagItem atIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">3</span><span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>invocation retainArguments<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>invocation performSelectorOnMainThread<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>invoke<span style="color: #002200;">&#41;</span> withObject<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> waitUntilDone<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p><strong>After:</strong></p>

<div class="wp_codebox"><table><tr id="p632721"><td class="code" id="p6327code21"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>reportAddProduct<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>Product <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>product toBagAs<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>BagItem <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>bagItem
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>delegate respondsToSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>onlineIntegrationManager<span style="color: #002200;">:</span>willAddProduct<span style="color: #002200;">:</span>toBagAs<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		dispatch_sync<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
			<span style="color: #002200;">&#91;</span>delegate onlineIntegrationManager<span style="color: #002200;">:</span>self willAddProduct<span style="color: #002200;">:</span>product toBagAs<span style="color: #002200;">:</span>bagItem<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The handy dispatch_sync on main queue can call any method, with any number of parameters on the main thread. The sync is equivalent to the waitUntilDone:YES. Since this allows for putting the main thread code inline you no longer need to have special methods that you then performSelectorOnMainThread:.</p>
<p>As a second note I found that it calls to the main thread should generally be done synchronously because I had a situation where a UILabel would not get updated if I did waitUntilDone:NO. Having everything as dispatch_sync now also takes care of that.</p>
<h3>Abusing the UIView Animation Context<br />
<h3>
<p>Before we had block based animation I would find myself often passing some context to the animationDidStopSelector so that I can do some wrap-up work when the animation is done. This is quite unsafe, even ARC complains about that unless you add a (__bridge id) to tell it to ignore the memory management of this object. </p>
<p>Context parameters didn&#8217;t get retained as a rule of thumb. In this example I needed to remove a view that has been animated out also from an internal dictionary after it was done. Having a dedicated instance variable would not have been an option because you could potentially have multiple animations going on at the same time.</p>
<p><strong>Before:</strong></p>

<div class="wp_codebox"><table><tr id="p632722"><td class="code" id="p6327code22"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>removalAnimationDidStop<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>animationID finished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>finished context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>context
<span style="color: #002200;">&#123;</span>
	UIView <span style="color: #002200;">*</span>removedView <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>__bridge UIView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>context;
&nbsp;
	<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> <span style="color: #002200;">*</span>oneKey <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span>self.viewsForItems allKeys<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		UIView <span style="color: #002200;">*</span>view <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.viewsForItems objectForKey<span style="color: #002200;">:</span>oneKey<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>view <span style="color: #002200;">==</span> removedView<span style="color: #002200;">&#41;</span>
		<span style="color: #002200;">&#123;</span>
			<span style="color: #002200;">&#91;</span>removedView removeFromSuperview<span style="color: #002200;">&#93;</span>;
			<span style="color: #002200;">&#91;</span>self.viewsForItems removeObjectForKey<span style="color: #002200;">:</span>oneKey<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#125;</span>
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// the above being called by:</span>
&nbsp;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> oneItem <span style="color: #a61390;">in</span> itemsToRemove<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// we must have a view for this item to remove it</span>
	__unsafe_unretained UIView <span style="color: #002200;">*</span>itemView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self viewForItem<span style="color: #002200;">:</span>oneItem<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>animated<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>UIView beginAnimations<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;ItemRemoval&quot;</span> context<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>__bridge <span style="color: #a61390;">void</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>itemView<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>UIView setAnimationDuration<span style="color: #002200;">:</span>deleteAnimationDuration<span style="color: #002200;">&#93;</span>;
		<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>delaySoFar&gt;<span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>
		<span style="color: #002200;">&#123;</span>
			<span style="color: #002200;">&#91;</span>UIView setAnimationDelay<span style="color: #002200;">:</span>delaySoFar<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#125;</span>
		<span style="color: #002200;">&#91;</span>UIView setAnimationBeginsFromCurrentState<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>UIView setAnimationDidStopSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>removalAnimationDidStop<span style="color: #002200;">:</span>finished<span style="color: #002200;">:</span>context<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>UIView setAnimationDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	itemView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
	itemView.transform <span style="color: #002200;">=</span>CGAffineTransformMakeScale<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0.5</span>, <span style="color: #2400d9;">0.5</span><span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>animated<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>UIView commitAnimations<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	delaySoFar <span style="color: #002200;">+=</span>deleteAnimationOffset;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p><strong>After:</strong></p>

<div class="wp_codebox"><table><tr id="p632723"><td class="code" id="p6327code23"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// moved into a convenience method</span>
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>removeCachedView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIView <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>removedView
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> <span style="color: #002200;">*</span>oneKey <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span>self.viewsForItems allKeys<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		UIView <span style="color: #002200;">*</span>view <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self.viewsForItems objectForKey<span style="color: #002200;">:</span>oneKey<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>view <span style="color: #002200;">==</span> removedView<span style="color: #002200;">&#41;</span>
		<span style="color: #002200;">&#123;</span>
			<span style="color: #002200;">&#91;</span>removedView removeFromSuperview<span style="color: #002200;">&#93;</span>;
			<span style="color: #002200;">&#91;</span>self.viewsForItems removeObjectForKey<span style="color: #002200;">:</span>oneKey<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#125;</span>
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// called from:</span>
&nbsp;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> oneItem <span style="color: #a61390;">in</span> itemsToRemove<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// we must have a view for this item to remove it</span>
	__unsafe_unretained UIView <span style="color: #002200;">*</span>itemView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self viewForItem<span style="color: #002200;">:</span>oneItem<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>animated?deleteAnimationDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>
						  delay<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>animated?delaySoFar<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>
						options<span style="color: #002200;">:</span>UIViewAnimationOptionBeginFromCurrentState 
					 animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
						 itemView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
						 itemView.transform <span style="color: #002200;">=</span>CGAffineTransformMakeScale<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0.5</span>, <span style="color: #2400d9;">0.5</span><span style="color: #002200;">&#41;</span>;
					 <span style="color: #002200;">&#125;</span> completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> finished<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
						 <span style="color: #002200;">&#91;</span>self removeCachedView<span style="color: #002200;">:</span>itemView<span style="color: #002200;">&#93;</span>;
					 <span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	delaySoFar <span style="color: #002200;">+=</span>deleteAnimationOffset;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>A boolean animated value can easily be replaced with a duration of 0. Animation delays are passed in the appropriate method and the beginsFromCurrentState is now a UIViewAnimationOption. This method is way safer because the blocks &#8220;capture&#8221; (i.e.) retain all the used variables making it impossible for the thing that was previously passed via the context to already been deallocated.</p>
<h3>Conclusion</h3>
<p>Sorry for not having more wise words to add here. The beauty of the possible simplifications you get if you decide to make iOS 4 your minimum deployment target should speak for itself.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6327&amp;md5=e15b14064d5e5b9cbd7d133de4682619" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/05/gcd-arc-blocks-oh-how-simple/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F05%2Fgcd-arc-blocks-oh-how-simple%2F&amp;language=en_GB&amp;category=text&amp;title=GCD%2C+ARC%2C+Blocks+%26%238211%3B+Oh+How+Simple%21&amp;description=I%26%238217%3Bm+%26%238220%3Btotally%26%238221%3B+migrating+my+iCatalog+framework+project+to+ARC%2C+GCD+and+blocks+and+I%26%238217%3Bd+like+to+share+with+you+some+of+the+revelations+that+the+use+of+these+modern+technologies...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Resource Bundles</title>
		<link>http://www.cocoanetics.com/2012/05/resource-bundles/</link>
		<comments>http://www.cocoanetics.com/2012/05/resource-bundles/#comments</comments>
		<pubDate>Tue, 01 May 2012 08:45:20 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6307</guid>
		<description><![CDATA[When shrink-wrapping your code for later reuse you inadvertenly will come into the situation that you have some resources (strings, XIBs, images et al) in your project that you also want to be reused. So what do you do? If only we had frameworks on iOS &#8230; then we could bundle the resources together with the code in a framework. But Apple does not want us to compile frameworks in Xcode since these could potentially contain code downloaded after the app review process. Popular projects like ShareKit or the Facebook iOS SDK have approached this dilemma by simply putting all resources into a folder, giving it the &#8220;.bundle&#8221; extension and instruct users of their SDK to also add this bundle to the &#8220;Copy Bundle Resources&#8221; step of their respective apps. In this here blog post I will show you a smarter way. &#160; There are several problems with having resources contained in a bundle and having this bundle be a member of any projects. Not Visible Xcode does not directly &#8220;see&#8221; the contents of the bundle, instead the pbxproj only contains a reference to the bundle folder. This causes trouble for apps like our Linguan that parses the project file to find strings (and soon XIB) files. It simply cannot see them. Here&#8217;s how it looks in the ShareKit project. If you ever see a x.bundle in a project you open, armed with the knowledge in this article, your reaction should be &#8220;that&#8217;s bad&#8221;. Of course the maintainers of these projects &#8220;have their reasons&#8221;. But I hope that by reading this you will agree with me that the reasons to not do it like this are better. Not Optimized Another issue is that this approach effectively disables the build time optimizations that Xcode carries out on the resources. strings files get converted into binary property lists XIB files get compiled into binary NIBs images get pngcrush-ed and many other actions for which there are build rules set up That means resources that are simply bundled (by means of copying them together) are slower and not optimized for the mobile devices. You probably wouldn&#8217;t notice that for only a hand full of items, but if you have a large number of resources then these delays will add up slowing down your app. And even if that does not bother you very much then the engineer inside of you should cringe. It just feels so dirty&#8230; Not Updating Another reason for why it is a bad idea to hide files from Xcode is that it simply won&#8217;t know to rebuild your app if you make a change in one of the files hidden in such a bundle. The Xcode build system has what is called dependencies. Implicit dependencies are source code files and resources that are part of certain targets. If such a dependence is modified then the incremental build process can determine which parts need to be re-compiled or re-optimized. Say you change something in a single .m file. Xcode will not rebuild the entire app, but only create the .o for this updated file and then link it with the previously built (and unchanged .o files). Same with resources. Xcode only replaces resources in the output product .app bundle if it knows they where modified. Resources in static bundles are invisible to Xcode and thus you always have to clean your build folder when doing a new build after changing them. Otherwise your updates will not propagate into your app. Enter the Resource Bundle Target Xcode, iOS and OS X have a mechanism to deal with folders that are looking like a single file but are actually containing multiple resources. This mechanism is modeled by the NSBundle class. You probably have worked with bundles before, namely the .app bundles that make up your app. Have you ever written [NSBundle mainBundle] before? I bet you did. For NSBundle to be able to manage bundles it requires a special info.plist inside the bundle that contains some meta information, like an internal identifier. But once you have the bundle set up correctly you have multiple great options for getting at the files as I will show you below. How to Set Up a Resource Bundle Product A resource bundle is a product that we will set up a target for. It just so happens that my DTPinLockController project is in need of some love, so it will serve as our example for this tutorial. As a first step I needed to move the files into the modern way of structuring my projects. That is, for component projects I have a Core and a Demo folder at the project root. Then each has a Source and a Resources sub-folder. DTPinLockController has XIBs, Images and Localizable.strings files. The source code goes into a Static Library [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/05/resource-bundles/"></g:plusone></div><p>When shrink-wrapping your code for later reuse you inadvertenly will come into the situation that you have some resources (strings, XIBs, images et al) in your project that you also want to be reused. So what do you do?</p>
<p>If only we had frameworks on iOS &#8230; then we could bundle the resources together with the code in a framework. But Apple does not want us to compile frameworks in Xcode since these could potentially contain code downloaded after the app review process.</p>
<p>Popular projects like <a href="https://github.com/ShareKit/ShareKit">ShareKit</a> or the <a href="https://github.com/facebook/facebook-ios-sdk">Facebook iOS SDK</a> have approached this dilemma by simply putting all resources into a folder, giving it the &#8220;.bundle&#8221; extension and instruct users of their SDK to also add this bundle to the &#8220;Copy Bundle Resources&#8221; step of their respective apps.</p>
<p>In this here blog post I will show you a smarter way.</p>
<p><span id="more-6307"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>There are several problems with having resources contained in a bundle and having this bundle be a member of any projects.</p>
<h3>Not Visible</h3>
<p>Xcode does not directly &#8220;see&#8221; the contents of the bundle, instead the pbxproj only contains a reference to the bundle folder. This causes trouble for apps like our <a href="http://www.cocoanetics.com/apps/linguan/">Linguan</a> that parses the project file to find strings (<a href="http://www.cocoanetics.com/2012/04/linguan-with-xib-support/">and soon XIB</a>) files. It simply cannot see them.</p>
<p>Here&#8217;s how it looks in the ShareKit project. If you ever see a x.bundle in a project you open, armed with the knowledge in this article, your reaction should be <em>&#8220;that&#8217;s bad&#8221;</em>.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-07.49.37.png"><img class="alignnone size-full wp-image-6308" title="ShareKit bundle" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-07.49.37.png" alt="" width="260" height="239" /></a></p>
<p>Of course the maintainers of these projects &#8220;have their reasons&#8221;. But I hope that by reading this you will agree with me that the reasons to not do it like this are better.</p>
<h3>Not Optimized</h3>
<p>Another issue is that this approach effectively disables the build time optimizations that Xcode carries out on the resources.</p>
<ul>
<li>strings files get converted into binary property lists</li>
<li>XIB files get compiled into binary NIBs</li>
<li>images get pngcrush-ed</li>
<li>and many other actions for which there are build rules set up</li>
</ul>
<p>That means resources that are simply bundled (by means of copying them together) are slower and not optimized for the mobile devices. You probably wouldn&#8217;t notice that for only a hand full of items, but if you have a large number of resources then these delays will add up slowing down your app. And even if that does not bother you very much then the engineer inside of you should cringe. It just feels so dirty&#8230;</p>
<h3>Not Updating</h3>
<p>Another reason for why it is a bad idea to hide files from Xcode is that it simply won&#8217;t know to rebuild your app if you make a change in one of the files hidden in such a bundle.</p>
<p>The Xcode build system has what is called dependencies. Implicit dependencies are source code files and resources that are part of certain targets. If such a dependence is modified then the incremental build process can determine which parts need to be re-compiled or re-optimized.</p>
<p>Say you change something in a single .m file. Xcode will not rebuild the entire app, but only create the .o for this updated file and then link it with the previously built (and unchanged .o files). Same with resources. Xcode only replaces resources in the output product .app bundle if it knows they where modified.</p>
<p>Resources in static bundles are invisible to Xcode and thus you always have to clean your build folder when doing a new build after changing them. Otherwise your updates will not propagate into your app.</p>
<h3>Enter the Resource Bundle Target</h3>
<p>Xcode, iOS and OS X have a mechanism to deal with folders that are looking like a single file but are actually containing multiple resources. This mechanism is modeled by the NSBundle class. You probably have worked with bundles before, namely the .app bundles that make up your app. Have you ever written [NSBundle mainBundle] before? I bet you did.</p>
<p>For NSBundle to be able to manage bundles it requires a special info.plist inside the bundle that contains some meta information, like an internal identifier. But once you have the bundle set up correctly you have multiple great options for getting at the files as I will show you below.</p>
<h3>How to Set Up a Resource Bundle Product</h3>
<p>A resource bundle is a product that we will set up a target for. It just so happens that my <a href="http://www.cocoanetics.com/parts/dtpinlockcontroller/">DTPinLockController</a> project is in need of some love, so it will serve as our example for this tutorial.</p>
<p>As a first step I needed to move the files into the modern way of structuring my projects. That is, for component projects I have a Core and a Demo folder at the project root. Then each has a Source and a Resources sub-folder. DTPinLockController has XIBs, Images and Localizable.strings files.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.22.31.png"><img class="alignnone size-full wp-image-6311" title="DTPinLockController Core tree" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.22.31.png" alt="" width="351" height="405" /></a></p>
<p>The source code goes into a Static Library target. All resources go into a Resource Bundle target. I&#8217;ve omitted the setup for the library here as we want to focus our attention on the resources.</p>
<p>Next we need to set up the Resource Bundle target. The template for this can be found in the OS X section, under &#8220;Framework &amp; Library&#8221;.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.36.15.png"><img class="alignnone  wp-image-6312" title="Bundle template" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.36.15.png" alt="" width="437" height="296" /></a></p>
<p>When removing the dynamic framework template Apple also removed the template for the Bundle. But with some minor modifications we can change the Mac bundle into one suitable for iOS. Since our bundle will not contain any executable code we don&#8217;t care about the settings for ARC and which foundation we want to use.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.39.12.png"><img class="alignnone  wp-image-6313" title="Creating the resource bundle target" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.39.12.png" alt="" width="437" height="296" /></a></p>
<p>I like to name the bundle product that same as my component so that in the end I have a DTPinLockController.bundle containing my resources and a libDTPinLockController.a library to go with it.</p>
<p>The template creates 3 files in DTPinLockController:</p>
<ul>
<li>an empty InfoPlist.strings file, we don&#8217;t need that</li>
<li>a DTPinLockController-Info.plist file, this is the META plist we need</li>
<li>a DTPinLockController-Prefix.pch file. No code in bundle means we can also remove that.</li>
</ul>
<p>I grab the plist and move it in to the root of my resources folder. The rest we can safely remove. I also rename it to Resources-Info.plist as to give an unsuspecting observer a hint that this is for the resource bundle.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.46.50.png"><img class="alignnone  wp-image-6314" title="The Resources Info.plist" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.46.50.png" alt="" width="583" height="203" /></a></p>
<p>We use this approach because the info plist for the resource bundle is too long to manually create. Note that there are several placeholders that get filled in during the build process, like the bundle name. All these settings come from the build settings which we are going to adjust next.</p>
<p>The default setting is to use the target name as name of products. I don&#8217;t like this because as I said about I want several products to be named DTPinLockController, but have the targets reflect their actual purpose.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.51.19.png"><img class="alignnone  wp-image-6315" title="Naming the targets" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-08.51.19.png" alt="" width="452" height="98" /></a></p>
<p>Because of this I end up with 3 targets with descriptive names like &#8220;Demo App&#8221;, &#8220;Static Library&#8221; and &#8220;Resource Bundle&#8221;. These have different product names &#8220;Demo&#8221;, &#8220;DTPinLockController&#8221; and &#8220;DTPinLockController&#8221; respectively. The different extensions and the prefix &#8220;lib&#8221; are automatically added by Xcode.</p>
<p>There are all the modifications we need to do on the build settings for the resource bundle:</p>
<ul>
<li>CMD-Backspace on the Base SDK to have it be the same as for the entire project: Latest iOS</li>
<li>Same on the &#8220;Mac OS X Deployment Target&#8221;</li>
<li>Same on the Architectures</li>
<li>Remove the reference to the PCH file</li>
<li>Remove &#8220;Installation Directory&#8221;</li>
<li>Set &#8220;Skip Install&#8221; to YES</li>
<li>Adjust &#8220;Info.plist File&#8221; to the correct path, e.g. Core/Resources/Resources-Info.plist</li>
</ul>
<p>The important part is the correct paths for the info plist and pch (none) and that Skip Install is YES because otherwise you get problems when trying to archive an app using the resource bundle. Since there is no code the compiler-related settings are really inconsequential, but I like to have them inherit from the project settings to have it look like a native iOS target.</p>
<p>In the build phases of the bundle target there is still a framework in &#8220;Link Binary with Libraries&#8221;. Remove this as well. It does not hurt as there is nothing to link it with, but might be confusing.</p>
<p>The final step for building the target is now to add the resources to it. You select the appropriate files in the project tree and set the checkmark in the right panel next to Resource Bundle.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.04.57.png"><img class="alignnone size-full wp-image-6316" title="Adding resources to the bundle" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.04.57.png" alt="" width="259" height="81" /></a></p>
<p>Xcode has added a scheme for the new target with the original name. So I remove all schemes and auto generate them from scratch. This will create one scheme per target and name them the same as the targets.</p>
<p>Then we can try and see if the bundle builds correctly.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.07.41.png"><img class="alignnone  wp-image-6317" title="Test-Build for the Resource Bundle" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.07.41.png" alt="" width="450" height="244" /></a></p>
<p>you can open up each build step and see that Xcode carried out the optimizations I alluded to above. In the case of this strings file you see &#8211;outputencoding binary that tells us that the strings file in the bundle will actually be binary.</p>
<p>You now have a DTPinLockController.bundle in the Products group that you can inspect to verify that this indeed is the case.</p>
<h3>Using the Resource Bundle</h3>
<p>There is a bug in Xcode 4.3.2 that might cause the list of resource to copy for the app target might get out of sync with the check marks in the project navigator. I had to manually go in the build phases of the demo app target and remove all the references to resources that are now part of the resource bundle.</p>
<p>Since the resource bundle is now a proper target we can add it as dependency to apps using it. This tells Xcode that if this dependency is somehow &#8220;dirty&#8221; then the app target is also in need of updating. So it will first build the dependent target and then include the product in the app build process.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.22.27.png"><img class="alignnone  wp-image-6318" title="Bildschirmfoto 2012-05-01 um 09.22.27" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.22.27.png" alt="" width="451" height="387" /></a></p>
<p>This shows the Static Library set up as dependency and in &#8220;Link Binary With Libraries&#8221;. Now we also want the bundle product to be in the &#8220;Copy Bundle Resources&#8221; phase. Click the Plus button and add the bundle product.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.27.57.png"><img class="alignnone size-full wp-image-6319" title="Bildschirmfoto 2012-05-01 um 09.27.57" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-05-01-um-09.27.57.png" alt="" width="403" height="465" /></a></p>
<p>This will make the bundle appear in the &#8220;Copy Bundle Resources&#8221;. If it wasn&#8217;t built before the app target then it will be built first, causing it to appear in the build products folder and from there it will be copied and included in the app product.</p>
<h3>A Few Code Changes</h3>
<p>If you reference images from a XIB and you put these images in the same resource bundle as the XIB then you don&#8217;t have to change anything. XIBs will load images from the same bundle that they were instantiated from.</p>
<p>However there are a couple of changes you need to make to your code so that the resources can be found at their new location.</p>
<h4>Strings</h4>
<p>The default macros for getting localized strings look for the strings files (aka &#8220;string tables&#8221;) in the main app bundle. These are the definitions of the 4 default macros and you can see that the bottom two have a way to specify the bundle to get the strings from whereas the first two hardcode the mainBundle.</p>

<div class="wp_codebox"><table><tr id="p630732"><td class="code" id="p6307code32"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define NSLocalizedString(key, comment) \</span>
	    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> mainBundle<span style="color: #002200;">&#93;</span> localizedStringForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>key<span style="color: #002200;">&#41;</span> value<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span> table<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>
<span style="color: #6e371a;">#define NSLocalizedStringFromTable(key, tbl, comment) \</span>
	    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> mainBundle<span style="color: #002200;">&#93;</span> localizedStringForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>key<span style="color: #002200;">&#41;</span> value<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span> table<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>tbl<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>
<span style="color: #6e371a;">#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \</span>
	    <span style="color: #002200;">&#91;</span>bundle localizedStringForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>key<span style="color: #002200;">&#41;</span> value<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span> table<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>tbl<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>
<span style="color: #6e371a;">#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) \</span>
	    <span style="color: #002200;">&#91;</span>bundle localizedStringForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>key<span style="color: #002200;">&#41;</span> value<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>val<span style="color: #002200;">&#41;</span> table<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>tbl<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span></pre></td></tr></table></div>

<p>You can create your own custom macro or category or what-have-you to have a shortcut, but to promote understanding here&#8217;s the entire code that we need to first get an NSBundle instance from our resource bundle and then get one string from it.</p>
<p>Note that specifying a table of nil means that the strings file is called &#8220;Localizable.strings&#8221;, for a table name of &#8220;Name&#8221; the file is called &#8220;Name.strings&#8221;</p>

<div class="wp_codebox"><table><tr id="p630733"><td class="code" id="p6307code33"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// get the resource bundle</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>resourceBundlePath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> mainBundle<span style="color: #002200;">&#93;</span> pathForResource<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DTPinLockController&quot;</span> ofType<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;bundle&quot;</span><span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> <span style="color: #002200;">*</span>resourceBundle <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> bundleWithPath<span style="color: #002200;">:</span>resourceBundlePath<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// get a string</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #a61390;">string</span> <span style="color: #002200;">=</span> NSLocalizedStringFromTableInBundle<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Set Passcode&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DTPinLockController&quot;</span>, resourceBundle, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;PinLock&quot;</span><span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>We probably want to have a category on NSBundle specific to our project to load and cache in a static variable the resource bundle. And to go with that a localized string macro that hard codes this resource bundle. </p>
<h4>XIBs</h4>
<p>You probably have several places where you call [super initWithNibName:@"MyViewController" bundle:nil]. The nil in this case causes the NIB loader to assume that you mean the main bundle. Just as easily we can get the resource bundle and pass there here instead.</p>

<div class="wp_codebox"><table><tr id="p630734"><td class="code" id="p6307code34"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// get the resource bundle</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>resourceBundlePath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> mainBundle<span style="color: #002200;">&#93;</span> pathForResource<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DTPinLockController&quot;</span> ofType<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;bundle&quot;</span><span style="color: #002200;">&#93;</span>;
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> <span style="color: #002200;">*</span>resourceBundle <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/"><span style="color: #400080;">NSBundle</span></a> bundleWithPath<span style="color: #002200;">:</span>resourceBundlePath<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// load View Controller from that</span>
UIViewController <span style="color: #002200;">*</span>vc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>MyViewController alloc<span style="color: #002200;">&#93;</span> initWithNibName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;MyViewController&quot;</span> bundle<span style="color: #002200;">:</span>resourceBundle<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>Do we see a pattern here? You betcha! We always first get the NSBundle instance for the resource bundle and then pass this as a parameter to some method that does something with the resource.</p>
<h4>Images</h4>
<p>Ah, Graphics. With strings and XIBs both working the same way you would only be right to assume that there&#8217;s a imageNamed:inBundle: method, BUT&#8230; it is private. Radar <a href="http://openradar.appspot.com/10250430">rdar://10250430</a> by Cedric Luthi addresses this.</p>
<p>But fortunately for us we don&#8217;t really need this special method. The regular imageNamed can work with our resource bundles too! </p>
<p>All you need to do is prefix your image names with the name of the bundle, like this:</p>

<div class="wp_codebox"><table><tr id="p630735"><td class="code" id="p6307code35"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// load image from resource bundle</span>
UIImage <span style="color: #002200;">*</span>image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DTPinLockController.bundle/Image.png&quot;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>This works because besides being a bundle object the resource bundle is also folder that can be traversed via its path.</p>
<p>The cool thing about loading XIBs, strings and images from resource bundles like this is that you retain the awesome powers of these methods. Like pathForResource:ofType: will automatically deliver the correct language version for the device if the resource is localized. Or imageNamed: will still automatically load Retina graphics where applicable or device-specific images with ~ipad or ~iphone.</p>
<p>I told you before that you don&#8217;t need to do anything special if these images are referenced from XIBs contained in the same resource bundle. So this is only necessary for the cases where you load the images from code.</p>
<h3>Conclusion</h3>
<p>This simplified tutorial has all targets and resource consumers in the same project. But the same concepts also work if you add the component project as a <a title="Sub-Projects in Xcode" href="http://www.cocoanetics.com/2011/12/sub-projects-in-xcode/">sub-project</a>.</p>
<p>I hope that I could convince you of the many advantages of resource bundles over static bundles. I&#8217;ve been successfully using them in almost all of my commercial components and many internal projects.</p>
<p>Bundle targets allow you to streamline the resource building process in a way that make larger projects way more effective and less error prone. Make it so!</p>
<p>&nbsp;</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6307&amp;md5=5e9da4bb56b97811bc4eacd8e3c6a0af" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/05/resource-bundles/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F05%2Fresource-bundles%2F&amp;language=en_GB&amp;category=text&amp;title=Resource+Bundles&amp;description=When+shrink-wrapping+your+code+for+later+reuse+you+inadvertenly+will+come+into+the+situation+that+you+have+some+resources+%28strings%2C+XIBs%2C+images+et+al%29+in+your+project+that+you+also...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Podcast #35 &#8211; &#8220;TapCaps&#8221;</title>
		<link>http://www.cocoanetics.com/2012/04/podcast-35-tapcaps/</link>
		<comments>http://www.cocoanetics.com/2012/04/podcast-35-tapcaps/#comments</comments>
		<pubDate>Sat, 28 Apr 2012 18:06:06 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6297</guid>
		<description><![CDATA[Episode 35, recorded Saturday, 28th of April 2012. &#8220;TapCaps&#8221; Alice Ning discusses the ins and outs of having a Kickstarter campaign for physical products versus software, we learn a bit about the magic behind capacitive touch screens and we learn what goes on behind the scenes of the TapCaps Kickstarter campaign. &#160; News The big news this week of course have been the record sales of WWDC 2012 tickets. Most of the people at the US west coast missed out on tickets because the rush was over in just 2 hours. Compared to 10 hours last year. This year Apple tried something new. Individuals could only purchase one ticket and company accounts could only purchase 5. Non-transferable, no refunds. Unfortunately the system to detect scalpers was a bit overzealous. Several people who used the same credit card and same IP address but different developer account received a cancellation notice from Apple. The problem with starting too early was that some people tried to purchase multiple individual tickets like this because at that time they couldn&#8217;t get hold of the company account agent. I&#8217;m keeping my fingers crossed that Apple can work this out, it is a bit of an embarrassing situation. Apple &#8211; as usual &#8211; trying an engineering approach with technology to solve the problem of scalping, but them stumbling over a stupid bug. Apple obviously wanted time the availability of tickets such that its early morning in the US, evening in Europe and before midnight in the far east. But what even surprised them was the speed at which the tickets went. Probably helped along very much by the WWDCalerts system that sent out messages to over 9000 people. I received my own such message about 10 minutes after the begin of the sales, that was 2:40 pm central european time. There where several people not so luck as SMS are known to be unreliable at times. Some received their notifications never or simply too late. Now two hours still twice as long as Google IO, but hey, people get free hardware there. I think we can attribute the breaking of last years record mostly to twitter and the alert system. I got lucky myself as well. I had my phone on silent so I totally missed the starting bell. But fortunately for me some nice chap sent me a direct message on Twitter. Which only further solidifies my theory that when people organize over social networks then they will break any record. Some other items, before we get to the interview. Pro Tip by Cédric Luthi: You must use MyImage@2x~ipad.png NOT MyImage~ipad@2x.png when using the automatic process of imageNamed. You know, imageNamed can automatically give you the @2x version on iOS devices with a Retina display. But did you know that it can also give you automatically a different image for iPhones and iPads? Yes, it does! You just call imageNamed:@&#8221;MyImage.png&#8221; and if there is a ~iPad between the 2x and the extension then this will be returned on iPads. But the order matters. It&#8217;s Name, @2x, tilde device, extension. Remember this. Shortly after being acquired by Facebook Instagram has opened up and nicely documented their API. You have an URL scheme to open instagram from your own app as well as web-based APIs to add and delete objects. In theory you could build your own Instagram client with that. Any takers? You probably won&#8217;t be purchased by Facebook though&#8230; Peter Steinberger reminds us: &#8220;If Xcode 4.4 creates an entitlement with NSFileProtectionComplete and your app fails to start up, just delete it. Stuff isn&#8217;t ready yet.&#8221; and he references a developer forum thread discussing this. Well you shouldn&#8217;t be using Xcode 4.4 in product environments yet, making production apps with&#8230; but that doesn&#8217;t prevent many individuals from doing exactly that. This is apparently already in iOS 5 as the mentioned thread is in the Core OS iOS 5 beta archive. No longer under NDA. So I can mention the official responds from an Apple engineer: One of my colleagues here in DTS discussed this issue with iOS engineering and the conclusion was that this stuff does not currently work. App Review Weather: Both new apps and app updates have improved to 99% chance of being reviewed in under 5 business days. Interview Alice Ning, management consultant by day, inventor by night, from Washington DC. Myth Busted: iPhones won&#8217;t work with Gloves TapCaps Campaign on Kickstarter  Alice Ning on Twitter, Homepage TheTapCaps.com]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/podcast-35-tapcaps/"></g:plusone></div><p>Episode 35, recorded Saturday, 28th of April 2012. &#8220;TapCaps&#8221;</p>
<p>Alice Ning discusses the ins and outs of having a Kickstarter campaign for physical products versus software, we learn a bit about the magic behind capacitive touch screens and we learn what goes on behind the scenes of the <a href="http://www.kickstarter.com/projects/ninglandia/tapcaps-the-phone-fooler">TapCaps Kickstarter campaign</a>.</p>

<p><span id="more-6297"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>News</h3>
<p>The big news this week of course have been the record sales of WWDC 2012 tickets. Most of the people at the US west coast missed out on tickets because the rush was over in just 2 hours. Compared to 10 hours last year.</p>
<p>This year Apple tried something new. Individuals could only purchase one ticket and company accounts could only purchase 5. Non-transferable, no refunds. Unfortunately the system to detect scalpers was a bit overzealous. Several people who used the same credit card and same IP address but different developer account received a cancellation notice from Apple.</p>
<p>The problem with starting too early was that some people tried to purchase multiple individual tickets like this because at that time they couldn&#8217;t get hold of the company account agent. I&#8217;m keeping my fingers crossed that Apple can work this out, it is a bit of an embarrassing situation. Apple &#8211; as usual &#8211; trying an engineering approach with technology to solve the problem of scalping, but them stumbling over a stupid bug.</p>
<p>Apple obviously wanted time the availability of tickets such that its early morning in the US, evening in Europe and before midnight in the far east. But what even surprised them was the speed at which the tickets went. Probably helped along very much by the WWDCalerts system that sent out messages to over 9000 people. I received my own such message about 10 minutes after the begin of the sales, that was 2:40 pm central european time. There where several people not so luck as SMS are known to be unreliable at times. Some received their notifications never or simply too late.</p>
<p>Now two hours still twice as long as Google IO, but hey, people get free hardware there. I think we can attribute the breaking of last years record mostly to twitter and the alert system. I got lucky myself as well. I had my phone on silent so I totally missed the starting bell. But fortunately for me some nice chap sent me a direct message on Twitter. Which only further solidifies my theory that when people organize over social networks then they will break any record.</p>
<p>Some other items, before we get to the interview.</p>
<p>Pro Tip by Cédric Luthi: You must use MyImage@2x~ipad.png NOT MyImage~ipad@2x.png when using the automatic process of imageNamed. You know, imageNamed can automatically give you the @2x version on iOS devices with a Retina display. But did you know that it can also give you automatically a different image for iPhones and iPads? Yes, it does! You just call imageNamed:@&#8221;MyImage.png&#8221; and if there is a ~iPad between the 2x and the extension then this will be returned on iPads. But the order matters. It&#8217;s Name, @2x, tilde device, extension. Remember this.</p>
<p>Shortly after being acquired by Facebook Instagram has opened up and nicely <a href="http://instagr.am/developer/">documented</a> their API. You have an URL scheme to open instagram from your own app as well as web-based APIs to add and delete objects. In theory you could build your own Instagram client with that. Any takers? You probably won&#8217;t be purchased by Facebook though&#8230;</p>
<p>Peter Steinberger reminds us: &#8220;If Xcode 4.4 creates an entitlement with NSFileProtectionComplete and your app fails to start up, just delete it. Stuff isn&#8217;t ready yet.&#8221; and he references a <a href="https://devforums.apple.com/message/627887">developer forum thread</a> discussing this. Well you shouldn&#8217;t be using Xcode 4.4 in product environments yet, making production apps with&#8230; but that doesn&#8217;t prevent many individuals from doing exactly that. This is apparently already in iOS 5 as the mentioned thread is in the Core OS iOS 5 beta archive. No longer under NDA. So I can mention the official responds from an Apple engineer:</p>
<blockquote><p>One of my colleagues here in DTS discussed this issue with iOS engineering and the conclusion was that this stuff does not currently work.</p></blockquote>
<p>App Review Weather: Both new apps and app updates have improved to <a href="https://developer.apple.com/news/">99% chance</a> of being reviewed in under 5 business days.</p>
<h3>Interview</h3>
<p>Alice Ning, management consultant by day, inventor by night, from Washington DC.</p>
<p><a title="Myth Busted: iPhones Won’t Work With Gloves" href="http://www.cocoanetics.com/2011/12/myth-busted-iphones-wont-work-with-gloves/">Myth Busted: iPhones won&#8217;t work with Gloves</a></p>
<p><a href="http://www.kickstarter.com/projects/ninglandia/tapcaps-the-phone-fooler">TapCaps Campaign on Kickstarter </a></p>
<p>Alice Ning <a href="http://www.twitter.com/ninglandia">on Twitter</a>, <a href="http://ninglandia.com/">Homepage</a></p>
<p><a href="http://TheTapCaps.com">TheTapCaps.com</a></p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6297&amp;md5=021328cd1b37e35617a67877e8455462" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/podcast-35-tapcaps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.cocoanetics.com/files/Cocoanetics_035.mp3" length="48650684" type="audio/mpeg" />
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fpodcast-35-tapcaps%2F&amp;language=en_GB&amp;category=text&amp;title=Podcast+%2335+%26%238211%3B+%26%238220%3BTapCaps%26%238221%3B&amp;description=Episode+35%2C+recorded+Saturday%2C+28th+of+April+2012.+%26%238220%3BTapCaps%26%238221%3B+Alice+Ning+discusses+the+ins+and+outs+of+having+a+Kickstarter+campaign+for+physical+products+versus+software%2C+we+learn+a+bit...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Linguan with XIB Support</title>
		<link>http://www.cocoanetics.com/2012/04/linguan-with-xib-support/</link>
		<comments>http://www.cocoanetics.com/2012/04/linguan-with-xib-support/#comments</comments>
		<pubDate>Sat, 28 Apr 2012 07:05:16 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Updates]]></category>
		<category><![CDATA[Linguan]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6292</guid>
		<description><![CDATA[I&#8217;ve seen it! The fabled XIB support for Linguan is almost done. &#160; A week ago I received a preview for the next version of Linguan which will also allow you to localize XIB files. Initially this will be facilitated by the ibtool tool which is contained in Xcode.app as well as gets installed in /usr/bin if you setup the command line tools. The guys at BytePoets &#8211; who we partnered with to make Linguan a reality &#8211; integrated it such that you can edit strings and XIB files with virtually no difference. Behind the scenes you have ibtool humming away extracting the tokens from the interface builder files and if you make a modification to write them back in. There are a few minor adjustments still necessary. For one there needs to be a preference setting to specify the path to ibtool. Without it the XIB functionality has to be disabled. Then we need to disable editing of the name column for tokens coming from a XIB because that&#8217;s the key that ibtool needs to send the updated string to the right place. If users can edit that it would probably cause trouble. I am hoping to have a similar approach as we did in the past with genstrings. You might remember that initially Linguan was calling the original genstrings, but I reverse-engineered a static library with the same functionality which is orders of magnitude faster. Once this was working properly we replaced the external function to an internal one. As soon as I have some time I hope to getting started with ibtool2 in a similar fashion. Write a GCD-multithreaded super-charged open-source version of ibtool that we can put in a static library and thus eliminate this external dependency. Oh, if you have not done so yet I strongly urge you to purchase Linguan now because we will definitely raise the price tag once XIB support is live. Also your purchase gives us the budget to add more exciting features in the future.]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/linguan-with-xib-support/"></g:plusone></div><p>I&#8217;ve seen it! The fabled XIB support for Linguan is almost done.</p>
<p><span id="more-6292"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>A week ago I received a preview for the next version of Linguan which will also allow you to localize XIB files. Initially this will be facilitated by the ibtool tool which is contained in Xcode.app as well as gets installed in /usr/bin if you setup the command line tools.</p>
<p>The guys at <a href="http://www.bytepoets.com">BytePoets</a> &#8211; who we partnered with to make Linguan a reality &#8211; integrated it such that you can edit strings and XIB files with virtually no difference. Behind the scenes you have ibtool humming away extracting the tokens from the interface builder files and if you make a modification to write them back in.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-28-um-08.55.49.png"><img class="alignnone  wp-image-6293" title="Linguan XIB picture proof" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-28-um-08.55.49.png" alt="" width="677" height="475" /></a></p>
<p>There are a few minor adjustments still necessary. For one there needs to be a preference setting to specify the path to ibtool. Without it the XIB functionality has to be disabled. Then we need to disable editing of the name column for tokens coming from a XIB because that&#8217;s the key that ibtool needs to send the updated string to the right place. If users can edit that it would probably cause trouble.</p>
<p>I am hoping to have a similar approach as we did in the past with genstrings. You might remember that initially Linguan was calling the original genstrings, but I reverse-engineered a static library with the <a title="genstrings2" href="http://www.cocoanetics.com/2012/01/genstrings2/">same functionality which is orders of magnitude faster</a>. Once this was working properly we replaced the external function to an internal one.</p>
<p>As soon as I have some time I hope to getting started with ibtool2 in a similar fashion. Write a GCD-multithreaded super-charged open-source version of ibtool that we can put in a static library and thus eliminate this external dependency.</p>
<p>Oh, if you have not done so yet I strongly urge you to <a href="http://itunes.apple.com/at/app/linguan/id477163052?mt=12">purchase Linguan now</a> because we will definitely raise the price tag once XIB support is live. Also your purchase gives us the budget to add more exciting features in the future.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6292&amp;md5=f055672f06886e137c635e849fed15d3" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/linguan-with-xib-support/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Flinguan-with-xib-support%2F&amp;language=en_GB&amp;category=text&amp;title=Linguan+with+XIB+Support&amp;description=I%26%238217%3Bve+seen+it%21+The+fabled+XIB+support+for+Linguan+is+almost+done.+%26nbsp%3B+A+week+ago+I+received+a+preview+for+the+next+version+of+Linguan+which+will+also+allow...&amp;tags=Linguan%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Creating a CoreData Model in Code</title>
		<link>http://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/</link>
		<comments>http://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 13:40:27 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6281</guid>
		<description><![CDATA[I&#8217;m working on my own file and image cache that uses CoreData for storage. The same way that NSURLCache is doing it, but with some optimizations that I know and understand. So I created DTDownloadCache and got it all working, but there was one minor thing that I didn&#8217;t like: The usual method of creating a CoreData entity model is by the entity editor built into Xcode. This meant that I had to include the .datamodeld file in apps using this. But I didn&#8217;t want to have to create a resource bundle just for this single file as you would have to do if you keep your reusable code in static libraries. Ugh! Fortunately there is a way how you can create a static model entirely in code so that you can make use of CoreData without having to ship an XML description of the model. &#160; First, lets have a quick look at how the model looked like in the editor. Plain and simple. The only special thing is to allow external storage for the fileData attribute. This allows CoreData to decide where to most efficiently store the file data. Small files will be stored in the entity itself. Large files get a GUID and will be saved in a subfolder of Library/Caches. If we wanted to support iOS 4 then we would have to create this mechanism ourselves which is available as of iOS 5. In XML this is represented as: The model is what CoreData needs to know how to translate between the SQLite database on disk and the managed objects in memory. Of course we could embed this model as a binary resource, but that would make out code unnecessarily more convoluted. I found a good example (Core Data Utility Tutorial) in the Apple documentation that explains the process. The method to create the same model as in the editor in code looks like this. ARC = On. - &#40;NSManagedObjectModel *&#41;_model &#123; NSManagedObjectModel *model = &#91;&#91;NSManagedObjectModel alloc&#93; init&#93;; &#160; // create the entity NSEntityDescription *entity = &#91;&#91;NSEntityDescription alloc&#93; init&#93;; &#91;entity setName:@&#34;DTCachedFile&#34;&#93;; &#91;entity setManagedObjectClassName:@&#34;DTCachedFile&#34;&#93;; &#160; // create the attributes NSMutableArray *properties = &#91;NSMutableArray array&#93;; &#160; NSAttributeDescription *remoteURLAttribute = &#91;&#91;NSAttributeDescription alloc&#93; init&#93;; &#91;remoteURLAttribute setName:@&#34;remoteURL&#34;&#93;; &#91;remoteURLAttribute setAttributeType:NSStringAttributeType&#93;; &#91;remoteURLAttribute setOptional:NO&#93;; &#91;remoteURLAttribute setIndexed:YES&#93;; &#91;properties addObject:remoteURLAttribute&#93;; &#160; NSAttributeDescription *fileDataAttribute = &#91;&#91;NSAttributeDescription alloc&#93; init&#93;; &#91;fileDataAttribute setName:@&#34;fileData&#34;&#93;; &#91;fileDataAttribute setAttributeType:NSBinaryDataAttributeType&#93;; &#91;fileDataAttribute setOptional:NO&#93;; &#91;fileDataAttribute setAllowsExternalBinaryDataStorage:YES&#93;; &#91;properties addObject:fileDataAttribute&#93;; &#160; NSAttributeDescription *lastAccessDateAttribute = &#91;&#91;NSAttributeDescription alloc&#93; init&#93;; &#91;lastAccessDateAttribute setName:@&#34;lastAccessDate&#34;&#93;; &#91;lastAccessDateAttribute setAttributeType:NSDateAttributeType&#93;; &#91;lastAccessDateAttribute setOptional:NO&#93;; &#91;properties addObject:lastAccessDateAttribute&#93;; &#160; NSAttributeDescription *expirationDateAttribute = &#91;&#91;NSAttributeDescription alloc&#93; init&#93;; &#91;expirationDateAttribute setName:@&#34;expirationDate&#34;&#93;; &#91;expirationDateAttribute setAttributeType:NSDateAttributeType&#93;; &#91;expirationDateAttribute setOptional:NO&#93;; &#91;properties addObject:expirationDateAttribute&#93;; &#160; NSAttributeDescription *contentTypeAttribute = &#91;&#91;NSAttributeDescription alloc&#93; init&#93;; &#91;contentTypeAttribute setName:@&#34;contentType&#34;&#93;; &#91;contentTypeAttribute setAttributeType:NSStringAttributeType&#93;; &#91;contentTypeAttribute setOptional:YES&#93;; &#91;properties addObject:contentTypeAttribute&#93;; &#160; NSAttributeDescription *fileSizeAttribute = &#91;&#91;NSAttributeDescription alloc&#93; init&#93;; &#91;fileSizeAttribute setName:@&#34;fileSize&#34;&#93;; &#91;fileSizeAttribute setAttributeType:NSInteger32AttributeType&#93;; &#91;fileSizeAttribute setOptional:NO&#93;; &#91;properties addObject:fileSizeAttribute&#93;; &#160; NSAttributeDescription *entityTagIdentifierAttribute = &#91;&#91;NSAttributeDescription alloc&#93; init&#93;; &#91;entityTagIdentifierAttribute setName:@&#34;entityTagIdentifier&#34;&#93;; &#91;entityTagIdentifierAttribute setAttributeType:NSStringAttributeType&#93;; &#91;entityTagIdentifierAttribute setOptional:YES&#93;; &#91;properties addObject:entityTagIdentifierAttribute&#93;; &#160; // add attributes to entity &#91;entity setProperties:properties&#93;; &#160; // add entity to model &#91;model setEntities:&#91;NSArray arrayWithObject:entity&#93;&#93;; &#160; return model; &#125; This looks more complicated than it really is because of the verbosity of Objective-C. The process is simply to create an empty model, create an entity, create the attributes, stir it all up and cook on medium flame for 15 minutes. If you compare this with the XML model above then you&#8217;ll see a couple of differences, but those are merely because I made my code model more strict, with less optional properties. The bare bones CoreData stack &#8211; consisting of the model, the persistent store coordinator and the managed object context might look like this: - &#40;void&#41;_setupCoreDataStack &#123; // setup managed object model &#160; /* NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@&#34;DTDownloadCache&#34; withExtension:@&#34;momd&#34;]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; */ &#160; // in code _managedObjectModel = &#91;self _model&#93;; &#160; // setup persistent store coordinator NSURL *storeURL = &#91;NSURL fileURLWithPath:&#91;&#91;NSString cachesPath&#93; stringByAppendingPathComponent:@&#34;DTDownload.cache&#34;&#93;&#93;; &#160; NSError *error = nil; _persistentStoreCoordinator = &#91;&#91;NSPersistentStoreCoordinator alloc&#93; initWithManagedObjectModel:_managedObjectModel&#93;; &#160; if &#40;!&#91;_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&#38;error&#93;&#41; &#123; // inconsistent model/store &#91;&#91;NSFileManager defaultManager&#93; removeItemAtURL:storeURL error:NULL&#93;; &#160; // retry once if &#40;!&#91;_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&#38;error&#93;&#41; &#123; NSLog&#40;@&#34;Unresolved error %@, %@&#34;, error, &#91;error userInfo&#93;&#41;; abort&#40;&#41;; &#125; &#125; &#160; // create MOC _managedObjectContext = &#91;&#91;NSManagedObjectContext alloc&#93; init&#93;; &#91;_managedObjectContext setPersistentStoreCoordinator:_persistentStoreCoordinator&#93;; &#125; Xcode turns the XML model into a momd file when building. The line that loads the model from this file is now commented out and instead the model is being constructed at runtime. You can modify the model until the first time it is used to access the persistent store. After that time it is read-only because changing it then would make it impossible for CoreData to talk to the data it has already saved. Also this approach does not bother with migrating models if something is changed. We simply remove the store file and retry adding the persistent store to the store coordinator. If that works then CoreData has created a fresh SQLite database [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/"></g:plusone></div><p>I&#8217;m working on my own file and image cache that uses CoreData for storage. The same way that NSURLCache is doing it, but with some optimizations that I know and understand. So I created DTDownloadCache and got it all working, but there was one minor thing that I didn&#8217;t like: The usual method of creating a CoreData entity model is by the entity editor built into Xcode.</p>
<p>This meant that I had to include the .datamodeld file in apps using this. But I didn&#8217;t want to have to create a resource bundle just for this single file as you would have to do if you keep your reusable code in static libraries. Ugh!</p>
<p>Fortunately there is a way how you can create a static model entirely in code so that you can make use of CoreData without having to ship an XML description of the model.</p>
<p><span id="more-6281"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>First, lets have a quick look at how the model looked like in the editor.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-27-um-2.28.42-PM.png"><img class="alignnone size-full wp-image-6282" title="Model in Editor" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-27-um-2.28.42-PM.png" alt="" width="619" height="323" /></a></p>
<p>Plain and simple. The only special thing is to allow external storage for the fileData attribute. This allows CoreData to decide where to most efficiently store the file data. Small files will be stored in the entity itself. Large files get a GUID and will be saved in a subfolder of Library/Caches. If we wanted to support iOS 4 then we would have to create this mechanism ourselves which is available as of iOS 5.</p>
<p>In XML this is represented as:</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-27-um-3.04.25-PM.png"><img class="alignnone size-full wp-image-6287" title="CoreData XML model" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-27-um-3.04.25-PM.png" alt="" width="719" height="241" /></a></p>
<p>The model is what CoreData needs to know how to translate between the SQLite database on disk and the managed objects in memory. Of course we could embed this model <a title="Embedding Binary Resources" href="http://www.cocoanetics.com/2010/10/embedding-binary-resources/">as a binary resource</a>, but that would make out code unnecessarily more convoluted. I found a good example (<a href="https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreDataUtilityTutorial/Articles/03_createModel.html">Core Data Utility Tutorial</a>) in the Apple documentation that explains the process.</p>
<p>The method to create the same model as in the editor in code looks like this. ARC = On.</p>

<div class="wp_codebox"><table><tr id="p628142"><td class="code" id="p6281code42"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectModel_Class/"><span style="color: #400080;">NSManagedObjectModel</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>_model
<span style="color: #002200;">&#123;</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectModel_Class/"><span style="color: #400080;">NSManagedObjectModel</span></a> <span style="color: #002200;">*</span>model <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectModel_Class/"><span style="color: #400080;">NSManagedObjectModel</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// create the entity</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSEntityDescription_Class/"><span style="color: #400080;">NSEntityDescription</span></a> <span style="color: #002200;">*</span>entity <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSEntityDescription_Class/"><span style="color: #400080;">NSEntityDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>entity setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DTCachedFile&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>entity setManagedObjectClassName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DTCachedFile&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// create the attributes</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>properties <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> <span style="color: #002200;">*</span>remoteURLAttribute <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>remoteURLAttribute setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;remoteURL&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>remoteURLAttribute setAttributeType<span style="color: #002200;">:</span>NSStringAttributeType<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>remoteURLAttribute setOptional<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>remoteURLAttribute setIndexed<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>properties addObject<span style="color: #002200;">:</span>remoteURLAttribute<span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> <span style="color: #002200;">*</span>fileDataAttribute <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>fileDataAttribute setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;fileData&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>fileDataAttribute setAttributeType<span style="color: #002200;">:</span>NSBinaryDataAttributeType<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>fileDataAttribute setOptional<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>fileDataAttribute setAllowsExternalBinaryDataStorage<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>properties addObject<span style="color: #002200;">:</span>fileDataAttribute<span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> <span style="color: #002200;">*</span>lastAccessDateAttribute <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>lastAccessDateAttribute setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lastAccessDate&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>lastAccessDateAttribute setAttributeType<span style="color: #002200;">:</span>NSDateAttributeType<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>lastAccessDateAttribute setOptional<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>properties addObject<span style="color: #002200;">:</span>lastAccessDateAttribute<span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> <span style="color: #002200;">*</span>expirationDateAttribute <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>expirationDateAttribute setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;expirationDate&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>expirationDateAttribute setAttributeType<span style="color: #002200;">:</span>NSDateAttributeType<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>expirationDateAttribute setOptional<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>properties addObject<span style="color: #002200;">:</span>expirationDateAttribute<span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> <span style="color: #002200;">*</span>contentTypeAttribute <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>contentTypeAttribute setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;contentType&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>contentTypeAttribute setAttributeType<span style="color: #002200;">:</span>NSStringAttributeType<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>contentTypeAttribute setOptional<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>properties addObject<span style="color: #002200;">:</span>contentTypeAttribute<span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> <span style="color: #002200;">*</span>fileSizeAttribute <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>fileSizeAttribute setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;fileSize&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>fileSizeAttribute setAttributeType<span style="color: #002200;">:</span>NSInteger32AttributeType<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>fileSizeAttribute setOptional<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>properties addObject<span style="color: #002200;">:</span>fileSizeAttribute<span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> <span style="color: #002200;">*</span>entityTagIdentifierAttribute <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/"><span style="color: #400080;">NSAttributeDescription</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>entityTagIdentifierAttribute setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;entityTagIdentifier&quot;</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>entityTagIdentifierAttribute setAttributeType<span style="color: #002200;">:</span>NSStringAttributeType<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>entityTagIdentifierAttribute setOptional<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>properties addObject<span style="color: #002200;">:</span>entityTagIdentifierAttribute<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// add attributes to entity</span>
	<span style="color: #002200;">&#91;</span>entity setProperties<span style="color: #002200;">:</span>properties<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// add entity to model</span>
	<span style="color: #002200;">&#91;</span>model setEntities<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> arrayWithObject<span style="color: #002200;">:</span>entity<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">return</span> model;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>This looks more complicated than it really is because of the verbosity of Objective-C. The process is simply to create an empty model, create an entity, create the attributes, stir it all up and cook on medium flame for 15 minutes. If you compare this with the XML model above then you&#8217;ll see a couple of differences, but those are merely because I made my code model more strict, with less optional properties.</p>
<p>The bare bones CoreData stack &#8211; consisting of the model, the persistent store coordinator and the managed object context might look like this:</p>

<div class="wp_codebox"><table><tr id="p628143"><td class="code" id="p6281code43"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>_setupCoreDataStack
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// setup managed object model</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">/*
	NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@&quot;DTDownloadCache&quot; withExtension:@&quot;momd&quot;];
	_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
	 */</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// in code</span>
	_managedObjectModel <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self _model<span style="color: #002200;">&#93;</span>; 
&nbsp;
	<span style="color: #11740a; font-style: italic;">// setup persistent store coordinator</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> <span style="color: #002200;">*</span>storeURL <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/"><span style="color: #400080;">NSURL</span></a> fileURLWithPath<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> cachesPath<span style="color: #002200;">&#93;</span> stringByAppendingPathComponent<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;DTDownload.cache&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/"><span style="color: #400080;">NSError</span></a> <span style="color: #002200;">*</span>error <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
	_persistentStoreCoordinator <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSPersistentStoreCoordinator_Class/"><span style="color: #400080;">NSPersistentStoreCoordinator</span></a> alloc<span style="color: #002200;">&#93;</span> initWithManagedObjectModel<span style="color: #002200;">:</span>_managedObjectModel<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>_persistentStoreCoordinator addPersistentStoreWithType<span style="color: #002200;">:</span>NSSQLiteStoreType configuration<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> URL<span style="color: #002200;">:</span>storeURL options<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> 
	<span style="color: #002200;">&#123;</span>
		<span style="color: #11740a; font-style: italic;">// inconsistent model/store</span>
		<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/"><span style="color: #400080;">NSFileManager</span></a> defaultManager<span style="color: #002200;">&#93;</span> removeItemAtURL<span style="color: #002200;">:</span>storeURL error<span style="color: #002200;">:</span><span style="color: #a61390;">NULL</span><span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #11740a; font-style: italic;">// retry once</span>
		<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>_persistentStoreCoordinator addPersistentStoreWithType<span style="color: #002200;">:</span>NSSQLiteStoreType configuration<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> URL<span style="color: #002200;">:</span>storeURL options<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> 
		<span style="color: #002200;">&#123;</span>
			NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Unresolved error %@, %@&quot;</span>, error, <span style="color: #002200;">&#91;</span>error userInfo<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
			<a href="http://www.opengroup.org/onlinepubs/009695399/functions/abort.html"><span style="color: #a61390;">abort</span></a><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
		<span style="color: #002200;">&#125;</span>
	<span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// create MOC</span>
	_managedObjectContext <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/"><span style="color: #400080;">NSManagedObjectContext</span></a> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>_managedObjectContext setPersistentStoreCoordinator<span style="color: #002200;">:</span>_persistentStoreCoordinator<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Xcode turns the XML model into a momd file when building. The line that loads the model from this file is now commented out and instead the model is being constructed at runtime. </p>
<p>You can modify the model until the first time it is used to access the persistent store. After that time it is read-only because changing it then would make it impossible for CoreData to talk to the data it has already saved.</p>
<p>Also this approach does not bother with migrating models if something is changed. We simply remove the store file and retry adding the persistent store to the store coordinator. If that works then CoreData has created a fresh SQLite database on disk that fits our new model.</p>
<h3>Conclusion</h3>
<p>CoreData is powerful to be used for maintaining the META information of caches and with the above approach you can easily keep your custom caches in static libraries without the need of adding a clunky model file to apps that are linking in this lib.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6281&amp;md5=1ec05d6a7dd1bb8c8ba1a5fe5f36edaf" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fcreating-a-coredata-model-in-code%2F&amp;language=en_GB&amp;category=text&amp;title=Creating+a+CoreData+Model+in+Code&amp;description=I%26%238217%3Bm+working+on+my+own+file+and+image+cache+that+uses+CoreData+for+storage.+The+same+way+that+NSURLCache+is+doing+it%2C+but+with+some+optimizations+that+I+know+and...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Disabling Facebook SSO, elegantly</title>
		<link>http://www.cocoanetics.com/2012/04/disabling-facebook-sso-elegantly/</link>
		<comments>http://www.cocoanetics.com/2012/04/disabling-facebook-sso-elegantly/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 11:40:15 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6271</guid>
		<description><![CDATA[The experts are still out as to the motivations behind Facebook&#8217;s iOS SDK strategy. But it is rather clear that if Facebook has their way then everybody is to be using their Single Sign-On (SSO) technique. Besides all potential advantages of having this SSO in place it has to leave your app for signing on. Not exactly something that is useful for all use cases. We have one case (involving ShareKit) which works better with the old style of signing into Facebook. This &#8220;traditional approach&#8221; shows the login dialog in a web pop up instead of leaving the app. In this post I&#8217;m sharing the 3 methods how to hack the Facebook class and bend it to our will. &#160; When researching for a way to disable SSO and restore the &#8220;old style&#8221; you inadvertently come across several people telling you to simply hack the authorize: method in Facebook.m. Original Code Hack The code for it is Open Source and so that poses little problem for a simple modification. You simply replace the method with the version below: - &#40;void&#41;authorize:&#40;NSArray *&#41;permissions &#123; &#91;self setValue:permissions forKey:@&#34;permissions&#34;&#93;; &#160; &#91;self authorizeWithFBAppAuth:NO safariAuth:NO&#93;; &#125; But unfortunately that means you&#8217;ll have to modify code that is owned by somebody else. And I&#8217;m not talking about licensing concerns but the simple fact that if Facebook updates the SDK you have to do this change every time after updating to the latest version. I am using the Facebook SDK via a submodule in ShareKit and I generally want to avoid having to keep track of modifications in third-party code. Which brings us to method number 2. Category Hack We know that we can add methods to existing classes by simply adding them in categories. If you have a method that has the same name as an existing method then the new method simply replaces the old one. So we can wrap the above hack in a category like so: Facebook+NoSSO.h #import &#34;Facebook.h&#34; &#160; @interface Facebook &#40;NoSSO&#41; &#160; - &#40;void&#41;authorize:&#40;NSArray *&#41;permissions; &#160; @end Facebook+NoSSO.m #import &#34;Facebook+NoSSO.h&#34; &#160; #import &#34;Facebook.h&#34; &#160; @interface Facebook &#40;&#41; &#160; - &#40;void&#41;authorizeWithFBAppAuth:&#40;BOOL&#41;tryFBAppAuth safariAuth:&#40;BOOL&#41;trySafariAuth; @end &#160; @implementation Facebook &#40;NoSSO&#41; &#160; - &#40;void&#41;authorize:&#40;NSArray *&#41;permissions &#123; &#91;self setValue:permissions forKey:@&#34;permissions&#34;&#93;; &#160; &#91;self authorizeWithFBAppAuth:NO safariAuth:NO&#93;; &#125; &#160; @end Notice that we need to define the authorizeWithFBAppAuth:safariAuth: in an anonymous category so that the compiler accepts us calling it from our own authorize: method. Without that we would get a compiler warning. This method is internal to the Facebook class and not exposed via the header. This method has two problems: 1) I don&#8217;t think that Apple actually guarantees a certain order in which classes and categories are loaded. So this is a bit risky to rely on it having always been working. 2) As of Xcode 4.3.2 the compiler will actually warn you &#8220;Category is implementing a method which will also be implemented by its primary class&#8221; Which brings us to the third &#8211; most elegant method. Swizzeling Hack Being dynamic in nature the Objective-C runtime allows us to dynamically changes classes and methods which our app is running. One such technique is called &#8220;Method Swizzeling&#8221; which basically means to exchange two methods. With this method you can substitute your own method implantation. First I borrowed some code from ShareKit and adapted it for general use in DTFoundation: NSObject+DTRuntime.h @interface NSObject &#40;DTRuntime&#41; &#160; + &#40;void&#41;swizzleMethod:&#40;SEL&#41;selector withMethod:&#40;SEL&#41;otherSelector; &#160; @end NSObject+DTRuntime.m #import &#60;objc/runtime.h&#62; &#160; @implementation NSObject &#40;DTRuntime&#41; &#160; + &#40;void&#41;swizzleMethod:&#40;SEL&#41;selector withMethod:&#40;SEL&#41;otherSelector &#123; // my own class is being targetted Class c = &#91;self class&#93;; &#160; // get the methods from the selectors Method originalMethod = class_getInstanceMethod&#40;c, selector&#41;; Method otherMethod = class_getInstanceMethod&#40;c, otherSelector&#41;; &#160; if &#40;class_addMethod&#40;c, selector, method_getImplementation&#40;otherMethod&#41;, method_getTypeEncoding&#40;otherMethod&#41;&#41;&#41; &#123; class_replaceMethod&#40;c, otherSelector, method_getImplementation&#40;originalMethod&#41;, method_getTypeEncoding&#40;originalMethod&#41;&#41;; &#125; else &#123; method_exchangeImplementations&#40;originalMethod, otherMethod&#41;; &#125; &#125; &#160; @end That takes care of the actual exchanging. I have to admit that I don&#8217;t quite understand the if, because in my tests it always ended up in the method_exchangeImplementations part. But as long as it is working&#8230; Now we have to only have a method with a unique name (to avoid the warning) and then we can exchange this method for the original authorize: method by means of this swizzle. The modified category now looks like this: Facebook+NoSSO.h #import &#34;Facebook.h&#34; &#160; @interface Facebook &#40;iCatalog&#41; &#160; - &#40;void&#41;authorize_noSSO:&#40;NSArray *&#41;permissions; &#160; + &#40;void&#41;toggleSingleSignOn; &#160; @end Facebook+NoSSO.m #import &#34;Facebook+iCatalog.h&#34; #import &#34;NSObject+DTRuntime.h&#34; &#160; @interface Facebook &#40;&#41; &#160; - &#40;void&#41;authorizeWithFBAppAuth:&#40;BOOL&#41;tryFBAppAuth safariAuth:&#40;BOOL&#41;trySafariAuth; @end &#160; @implementation Facebook &#40;iCatalog&#41; &#160; - &#40;void&#41;authorize_noSSO:&#40;NSArray *&#41;permissions &#123; &#91;self setValue:permissions forKey:@&#34;permissions&#34;&#93;; &#160; &#91;self authorizeWithFBAppAuth:NO safariAuth:NO&#93;; &#125; &#160; + &#40;void&#41;toggleSingleSignOn &#123; &#91;Facebook swizzleMethod:@selector&#40;authorize:&#41; withMethod:@selector&#40;authorize_noSSO:&#41;&#93;; &#125; &#160; @end You see that I have also added a class method to toggle SSO on and off. I named it &#8220;toggle&#8221; because each call will exchange the two method implementations. While the first toggle will disable SSO the second call restores the original method and thus [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/disabling-facebook-sso-elegantly/"></g:plusone></div><p>The experts are still out as to the motivations behind Facebook&#8217;s iOS SDK strategy. But it is rather clear that if Facebook has their way then everybody is to be using their Single Sign-On (SSO) technique. Besides all potential advantages of having this SSO in place it has to leave your app for signing on. </p>
<p>Not exactly something that is useful for all use cases. We have one case (involving ShareKit) which works better with the old style of signing into Facebook. This &#8220;traditional approach&#8221; shows the login dialog in a web pop up instead of leaving the app. </p>
<p>In this post I&#8217;m sharing the 3 methods how to hack the Facebook class and bend it to our will.</p>
<p><span id="more-6271"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>When researching for a way to disable SSO and restore the &#8220;old style&#8221; you inadvertently come across several people telling you to simply hack the authorize: method in Facebook.m. </p>
<h3>Original Code Hack</h3>
<p>The code for it is <a href="https://github.com/facebook/facebook-ios-sdk">Open Source</a> and so that poses little problem for a simple modification. You simply replace the method with the version below:</p>

<div class="wp_codebox"><table><tr id="p627154"><td class="code" id="p6271code54"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>authorize<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>permissions 
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>self setValue<span style="color: #002200;">:</span>permissions forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;permissions&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>self authorizeWithFBAppAuth<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span> safariAuth<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>But unfortunately that means you&#8217;ll have to modify code that is owned by somebody else. And I&#8217;m not talking about licensing concerns but the simple fact that if Facebook updates the SDK you have to do this change every time after updating to the latest version. </p>
<p>I am using the Facebook SDK via a submodule in ShareKit and I generally want to avoid having to keep track of modifications in third-party code. Which brings us to method number 2.</p>
<h3>Category Hack</h3>
<p>We know that we can add methods to existing classes by simply adding them in categories. If you have a method that has the same name as an existing method then the new method simply replaces the old one. So we can wrap the above hack in a category like so:</p>
<p><strong>Facebook+NoSSO.h</strong></p>

<div class="wp_codebox"><table><tr id="p627155"><td class="code" id="p6271code55"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;Facebook.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> Facebook <span style="color: #002200;">&#40;</span>NoSSO<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>authorize<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>permissions;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><strong>Facebook+NoSSO.m</strong></p>

<div class="wp_codebox"><table><tr id="p627156"><td class="code" id="p6271code56"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;Facebook+NoSSO.h&quot;</span>
&nbsp;
<span style="color: #6e371a;">#import &quot;Facebook.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> Facebook <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>authorizeWithFBAppAuth<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>tryFBAppAuth
                    safariAuth<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>trySafariAuth;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> Facebook <span style="color: #002200;">&#40;</span>NoSSO<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>authorize<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>permissions 
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>self setValue<span style="color: #002200;">:</span>permissions forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;permissions&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>self authorizeWithFBAppAuth<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span> safariAuth<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>Notice that we need to define the authorizeWithFBAppAuth:safariAuth: in an anonymous category so that the compiler accepts us calling it from our own authorize: method. Without that we would get a compiler warning. This method is internal to the Facebook class and not exposed via the header.</p>
<p>This method has two problems: 1) I don&#8217;t think that Apple actually guarantees a certain order in which classes and categories are loaded. So this is a bit risky to rely on it having always been working. 2) As of Xcode 4.3.2 the compiler will actually warn you <em>&#8220;Category is implementing a method which will also be implemented by its primary class&#8221;</em> </p>
<p>Which brings us to the third &#8211; most elegant method.</p>
<h3>Swizzeling Hack</h3>
<p>Being dynamic in nature the Objective-C runtime allows us to dynamically changes classes and methods which our app is running. One such technique is called &#8220;Method Swizzeling&#8221; which basically means to exchange two methods. With this method you can substitute your own method implantation.</p>
<p>First I borrowed some code from ShareKit and adapted it for general use in DTFoundation:</p>
<p><strong>NSObject+DTRuntime.h</strong></p>

<div class="wp_codebox"><table><tr id="p627157"><td class="code" id="p6271code57"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> <span style="color: #002200;">&#40;</span>DTRuntime<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>swizzleMethod<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>selector withMethod<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>otherSelector;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><strong>NSObject+DTRuntime.m</strong></p>

<div class="wp_codebox"><table><tr id="p627158"><td class="code" id="p6271code58"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;objc/runtime.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/"><span style="color: #400080;">NSObject</span></a> <span style="color: #002200;">&#40;</span>DTRuntime<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>swizzleMethod<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>selector withMethod<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">SEL</span><span style="color: #002200;">&#41;</span>otherSelector
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// my own class is being targetted</span>
	<span style="color: #a61390;">Class</span> c <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self class<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// get the methods from the selectors</span>
	Method originalMethod <span style="color: #002200;">=</span> class_getInstanceMethod<span style="color: #002200;">&#40;</span>c, selector<span style="color: #002200;">&#41;</span>;
	Method otherMethod <span style="color: #002200;">=</span> class_getInstanceMethod<span style="color: #002200;">&#40;</span>c, otherSelector<span style="color: #002200;">&#41;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>class_addMethod<span style="color: #002200;">&#40;</span>c, selector, method_getImplementation<span style="color: #002200;">&#40;</span>otherMethod<span style="color: #002200;">&#41;</span>, method_getTypeEncoding<span style="color: #002200;">&#40;</span>otherMethod<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		class_replaceMethod<span style="color: #002200;">&#40;</span>c, otherSelector, method_getImplementation<span style="color: #002200;">&#40;</span>originalMethod<span style="color: #002200;">&#41;</span>, method_getTypeEncoding<span style="color: #002200;">&#40;</span>originalMethod<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span>
	<span style="color: #a61390;">else</span>
	<span style="color: #002200;">&#123;</span>
		method_exchangeImplementations<span style="color: #002200;">&#40;</span>originalMethod, otherMethod<span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>That takes care of the actual exchanging. I have to admit that I don&#8217;t quite understand the if, because in my tests it always ended up in the method_exchangeImplementations part. But as long as it is working&#8230; <img src='http://www.cocoanetics.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Now we have to only have a method with a unique name (to avoid the warning) and then we can exchange this method for the original authorize: method by means of this swizzle. The modified category now looks like this:</p>
<p><strong>Facebook+NoSSO.h</strong></p>

<div class="wp_codebox"><table><tr id="p627159"><td class="code" id="p6271code59"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;Facebook.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> Facebook <span style="color: #002200;">&#40;</span>iCatalog<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>authorize_noSSO<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>permissions;
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>toggleSingleSignOn;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p><strong>Facebook+NoSSO.m</strong></p>

<div class="wp_codebox"><table><tr id="p627160"><td class="code" id="p6271code60"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;Facebook+iCatalog.h&quot;</span>
<span style="color: #6e371a;">#import &quot;NSObject+DTRuntime.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> Facebook <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>authorizeWithFBAppAuth<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>tryFBAppAuth
                    safariAuth<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>trySafariAuth;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> Facebook <span style="color: #002200;">&#40;</span>iCatalog<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>authorize_noSSO<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>permissions 
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>self setValue<span style="color: #002200;">:</span>permissions forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;permissions&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #002200;">&#91;</span>self authorizeWithFBAppAuth<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span> safariAuth<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>toggleSingleSignOn
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>Facebook swizzleMethod<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>authorize<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span> withMethod<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>authorize_noSSO<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>You see that I have also added a class method to toggle SSO on and off. I named it &#8220;toggle&#8221; because each call will exchange the two method implementations. While the first toggle will disable SSO the second call restores the original method and thus re-enables it.</p>
<p>With this you only have to call the toggleSingleSignOn once per app launch, the best place is the app delegate&#8217;s +initialize which is guaranteed to be called just once and also in a thread-safe manner.</p>

<div class="wp_codebox"><table><tr id="p627161"><td class="code" id="p6271code61"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@implementation</span> MyAppDelegate
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>initialize
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// disable Facebook SSO</span>
	<span style="color: #002200;">&#91;</span>Facebook toggleSingleSignOn<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>That&#8217;s all it takes. </p>
<h3>Conclusion</h3>
<p>Of the three ways how you can modify somebody else&#8217;s code&#8217;s behavior the one that actually replaces the implementation via swizzeling is the most convenient and least dangerous, at least if you know what you are doing.</p>
<p>This alternative does not have the drawback of original code hacking that you incur an additional maintenance overhead. And it does not have the drawback of compiler warnings for the category hack approach.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6271&amp;md5=939d9a1be0be870d11af3c9ccc9faee2" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/disabling-facebook-sso-elegantly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fdisabling-facebook-sso-elegantly%2F&amp;language=en_GB&amp;category=text&amp;title=Disabling+Facebook+SSO%2C+elegantly&amp;description=The+experts+are+still+out+as+to+the+motivations+behind+Facebook%26%238217%3Bs+iOS+SDK+strategy.+But+it+is+rather+clear+that+if+Facebook+has+their+way+then+everybody+is+to+be...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>On the Future of Remote Working</title>
		<link>http://www.cocoanetics.com/2012/04/on-the-future-of-remote-working/</link>
		<comments>http://www.cocoanetics.com/2012/04/on-the-future-of-remote-working/#comments</comments>
		<pubDate>Sun, 22 Apr 2012 07:26:48 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Feedback]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6263</guid>
		<description><![CDATA[I read an article by Michael Abrash on the Valve blog that he signed up with Valve to investigate Augmented Reality. At the end of his article he mentions that Valve is hiring. This prompted me to send him the following long email. And as I like for my writing to not go to waste I am posting it here as well. &#160; Hi Michael, I read the Valve employee handbook directly followed by your great article. There are many concepts in Valve&#8217;s philosophy that resonate with me. However I have the same problem that most people who read this have: Geography. Granted, anybody is &#8211; theoretically &#8211; free to move to live near Valve&#8217;s Headquarters and few people do&#8230; The handbook mentioned like 44 international hires so far. This number is so low because of several obvious reasons too few H1B visas most engineering jobs in the USA require a bachelor&#8217;s degree or higher &#8230; Because that&#8217;s needed for the visa &#8230; But in many countries the education of engineers is vocational and not academic and therefore people have no such academic degree and it is quite a fuss to formally prove that the education and/or experience is equivalent. very few people are actually willing to move to the USA because the the quality of living is far greater elsewhere &#8230; Or they are married (like myself) and there is no chance our wives would ever consent to moving away from our rural town, let alone to the USA But I am not writing to you because I am whining. I want to open your eyes to a problem that technology companies in the USA are facing. And where there is a problem an engineer will work on a solution. To give an analog from recent history: if people ship physical goods the recipient has to pay customs taxes. This is why a recent Kickstarter project has a rewards tier that is entirely virtual. You get everything in digital form and downloadable over the internet as to not having to pay any customs or taxes for it. Which brings me to the point I want to address: somebody needs to invent a way that somebody in a foreign country could work at Valve virtually. Basically a level of cyberspace that is of sufficient fidelity that it can replace actual in-person presence. There&#8217;s another Kickstarter project that went into this direction. It was a robotic cradle for an iPhone that you could remote control. The need to see and hear from a remote location, enhanced by the need that you want to be able to change the perspective. Granted there are some ways how companies try to address this: Skype, Go2Meeting, video chat, Sharepoint. The most innovative development probably being Microsoft&#8217;s RoundTable device. But they all fall short because they simply don&#8217;t have the multi-disciplinary makeup of researchers that you need to solve this hard problem. 3D-Graphics and Immersion and virtual worlds and internetworking have always been the forté of Game companies like Valve. Companies like Google or Microsoft are working on small slices of the problem as they understand it. But where is the enthusiasm for immersive cyberspace that we all felt 20 years ago? 3D TV has become an &#8220;also ran&#8221;, cyperspace is no longer of interest for anybody, even Google with their glasses project is only focussing on displaying information (and probably enhance our reality with ads). The great opportunity for Valve is to enhance the Source engine in several key areas: revolutionise motion capture and eliminate the need for markers implement real time 3D tracking and &#8220;world building&#8221; develop real time interpolation between these 3D scans let multiple such live 3D scanners work in tandem on internetworked servers develop mobile clients that can tap into these worlds and navigate them develop technology that can insert a remote worker&#8217;s avatar into your current reality I think that the sub-problem of real time scanning and world construction can be solved sooner than the problem of how to get this onto people&#8217;s retinas. But the immediate benefits would be a dramatic increase in productivity for 3D graphics as used in computer animated and 3D live action movies. Also I think many people would be interested in being able to go into a room, taking a look around once and then having a 3D model of that for later use. Sort of like the holo cam that Lt. Data had as a hobby in Star Trek: TNG. Again it has to be a Gaming company to provide the technology for this next paradigm shift. Camcorder companies can only increase the number of pixels on their CCDs. And their &#8220;solution&#8221; for the 3D model problem is to not solve it, but let the viewer&#8217;s brain figure this out. The next quantum leap in [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/on-the-future-of-remote-working/"></g:plusone></div><p>I read an article by Michael Abrash <a href="http://blogs.valvesoftware.com/abrash/valve-how-i-got-here-what-its-like-and-what-im-doing-2/">on the Valve blog</a> that he signed up with Valve to investigate Augmented Reality. At the end of his article he mentions that Valve is hiring.</p>
<p>This prompted me to send him the following long email. And as I like for my writing to not go to waste I am posting it here as well.</p>
<p><span id="more-6263"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>Hi Michael,</p>
<p>I read the Valve employee handbook directly followed by your great article. There are many concepts in Valve&#8217;s philosophy that resonate with me. However I have the same problem that most people who read this have: Geography.</p>
<p>Granted, anybody is &#8211; theoretically &#8211; free to move to live near Valve&#8217;s Headquarters and few people do&#8230; The handbook mentioned like 44 international hires so far. This number is so low because of several obvious reasons</p>
<ul>
<li>too few H1B visas</li>
<li>most engineering jobs in the USA require a bachelor&#8217;s degree or higher</li>
<li>&#8230; Because that&#8217;s needed for the visa</li>
<li>&#8230; But in many countries the education of engineers is vocational and not academic and therefore people have no such academic degree and it is quite a fuss to formally prove that the education and/or experience is equivalent.</li>
<li>very few people are actually willing to move to the USA because the the quality of living is far greater elsewhere</li>
<li>&#8230; Or they are married (like myself) and there is no chance our wives would ever consent to moving away from our rural town, let alone to the USA</li>
</ul>
<p>But I am not writing to you because I am whining. I want to open your eyes to a problem that technology companies in the USA are facing. And where there is a problem an engineer will work on a solution.</p>
<p>To give an analog from recent history: if people ship physical goods the recipient has to pay customs taxes. This is why a recent Kickstarter project has a rewards tier that is entirely virtual. You get everything in digital form and downloadable over the internet as to not having to pay any customs or taxes for it.</p>
<p>Which brings me to the point I want to address: somebody needs to invent a way that somebody in a foreign country could <strong>work at Valve virtually</strong>. Basically a level of cyberspace that is of sufficient fidelity that it can replace actual in-person presence. There&#8217;s another Kickstarter project that went into this direction. It was a robotic cradle for an iPhone that you could remote control. The need to see and hear from a remote location, enhanced by the need that you want to be able to change the perspective.</p>
<p>Granted there are some ways how companies try to address this: Skype, Go2Meeting, video chat, Sharepoint. The most innovative development probably being Microsoft&#8217;s RoundTable device. But they all fall short because they simply don&#8217;t have the multi-disciplinary makeup of researchers that you need to solve this hard problem.</p>
<p>3D-Graphics and Immersion and virtual worlds and internetworking have always been the forté of Game companies like Valve. Companies like Google or Microsoft are working on small slices of the problem as they understand it. But where is the enthusiasm for immersive cyberspace that we all felt 20 years ago?</p>
<p>3D TV has become an &#8220;also ran&#8221;, cyperspace is no longer of interest for anybody, even Google with their glasses project is only focussing on displaying information (and probably enhance our reality with ads).</p>
<p>The great opportunity for Valve is to enhance the Source engine in several key areas:</p>
<ul>
<li>revolutionise motion capture and eliminate the need for markers</li>
<li>implement real time 3D tracking and &#8220;world building&#8221;</li>
<li>develop real time interpolation between these 3D scans</li>
<li>let multiple such live 3D scanners work in tandem on internetworked servers</li>
<li>develop mobile clients that can tap into these worlds and navigate them</li>
<li>develop technology that can insert a remote worker&#8217;s avatar into your current reality</li>
</ul>
<p>I think that the sub-problem of real time scanning and world construction can be solved sooner than the problem of how to get this onto people&#8217;s retinas. But the immediate benefits would be a dramatic increase in productivity for 3D graphics as used in computer animated and 3D live action movies. Also I think many people would be interested in being able to go into a room, taking a look around once and then having a 3D model of that for later use.</p>
<p>Sort of like the holo cam that Lt. Data had as a hobby in Star Trek: TNG.</p>
<p>Again it has to be a Gaming company to provide the technology for this next paradigm shift. Camcorder companies can only increase the number of pixels on their CCDs. And their &#8220;solution&#8221; for the 3D model problem is to not solve it, but let the viewer&#8217;s brain figure this out.</p>
<p>The next quantum leap in vision technology will no longer be to record pixels, but to record an actual 3D model of the real world. And I think this will come as a side-product of the greater goal of being able to &#8220;beam&#8221; reality to other places on earth for virtual consumption first and actual participation later.</p>
<p>Speaking of consumption &#8230; Could you please check on the progress of HL2:ep3? <img src='http://www.cocoanetics.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Kind regards</p>
<p>Oliver Drobnik</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6263&amp;md5=33e2ba86e26c74390eb9fdedb9c7107f" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/on-the-future-of-remote-working/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fon-the-future-of-remote-working%2F&amp;language=en_GB&amp;category=text&amp;title=On+the+Future+of+Remote+Working&amp;description=I+read+an+article+by+Michael+Abrash+on+the+Valve+blog+that+he+signed+up+with+Valve+to+investigate+Augmented+Reality.+At+the+end+of+his+article+he+mentions+that...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Podcast #34 &#8211; &#8220;Be Excellent And Valuable&#8221;</title>
		<link>http://www.cocoanetics.com/2012/04/podcast-34-be-excellent-and-valuable/</link>
		<comments>http://www.cocoanetics.com/2012/04/podcast-34-be-excellent-and-valuable/#comments</comments>
		<pubDate>Sat, 21 Apr 2012 16:02:59 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6242</guid>
		<description><![CDATA[Episode 34, recorded Saturday April 21th, 2012 We can learn about cool company philosophy from the Valve employee handbook, Objective-C is creeping up to C++ as the world&#8217;s almost most favorite programming language. And iOS 4 can now  be retired. &#160; Show Notes Still no WWDC, some people start to get nervous and some even try to jinx it. Marco Arment, of Instapaper, would prefer if WWDC 2012 didn&#8217;t happen in the week from June 11th through 15th because that would mean he couldn&#8217;t spent his birthday at home which falls in this interval. There are no other obvious candidate dates for WWDC so we keep on being stressed out by Apple with every passing day. And yes, I am stressed too. Aren&#8217;t we all&#8230; for the next big update to my iCatalog framework I&#8217;ve spent the last week to migrate everything to ARC. The whole project started out as one iPad app and over time the number of target has grown exponentially. We&#8217;re now developing some more advanced features but decided that these will be iOS 5 only. So &#8211; of course &#8211; I&#8217;m switching to ARC. And of course there is ShareKit which has no hope of being migrated to ARC soon, so I had to pack that into its own static library with ARC turned off. In the end I want the iCatalog project to be only for the core functionality. All the iCatalog apps should be in a different project so that I don&#8217;t have to mess with the dozens of targets for all the catalog apps any more. I am telling you this for two reasons: 1) as an excuse for not having a better show prepared. and 2) as a pointer that you might want to have reusable core functionality also in your own modules and sub- projects. Oh, and I have another excuse: my MacBook Air is still being repaired. I suspect that the power regulator had a problem. Sometimes it wouldn&#8217;t charge, then it would. If you were lucky you could start it, but then it would shut down by itself after a short while. And then you couldn&#8217;t start it until you reset it with these secret key combinations. But fortunately I have AppleCare for it and so that should be fixed next week. And now for some interesting news &#8230; yes there where a few&#8230; TIOBE Software publishes their Programming Community Index every month. This is sort of a hit parade of programming languages somehow measured by an elaborate methodology that uses search engines to determine the relative importance of programming languages. In the current April report the top position went to C which overtook Java on second place compared to a year ago. C++ stayed put on third place. The big winner in the top 10 is Objective-C which moved from 8th place last April to number 4. Objective-C also became the &#8220;Language of the year&#8221; in 2011 because it seems to be rising in these ranks like a rocket. All of us iOS and Mac developers using this for our favorite platform probably helps here quite a bit. Google Currents launched internationally this month, after almost half a year being US-only. Will Kiefer, the iOS developer behind Google Currents, told me that they too make widespread use of UIWebViews for the main reason that their online publishing tool requires Javascript to run and that only the HTML5 CSS support in web views allows them to expose the customizability for their content partners. Will told me that to speed up image loading he replaced the normal NSURLCache mechanism with NSURLProtocol. This is faster because NSURLCache can only return one cached response at a time while NSURLProtocol can work concurrently. That&#8217;s definitely something worth looking into. I&#8217;m trying to get Will on the Cocoanetics podcast in one of the next episodes. LLVM.org published in much greater detail the new Objective-C literal syntax for NSNumbers and Containers. Users of Apple&#8217;s compiler will be able to start using these features with Apple LLVM Compiler 4.0. Users of open-source LLVM.org compiler releases can use these features starting with clang v3.1. The 4.0 compiler will be in Xcode 4.4 which is due out about the same time as OS X Mountain Lion sometime this summer. The good thing will be that since this is compile-time technology it will mean that we should be able to use the new Literal syntax also in older iOS versions. Valve software, makers of Steam and amazing games like Half-Life, have published a copy of their new employee handbook online. This manual is supposed to give new hires an overview of the Valve company philosophy. I recommend that you download this book and read it on your iPad because it is truly a piece of art. The manual in itself is [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/podcast-34-be-excellent-and-valuable/"></g:plusone></div><p>Episode 34, recorded Saturday April 21th, 2012</p>
<p>We can learn about cool company philosophy from the Valve employee handbook, Objective-C is creeping up to C++ as the world&#8217;s almost most favorite programming language. And iOS 4 can now  be retired.</p>

<p><span id="more-6242"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>Show Notes</h3>
<p>Still no WWDC, some people start to get nervous and some even try to jinx it. Marco Arment, of Instapaper, would prefer if WWDC 2012 didn&#8217;t happen in the week from June 11th through 15th because that would mean he couldn&#8217;t spent his birthday at home which falls in this interval. There are no other obvious candidate dates for WWDC so we keep on being stressed out by Apple with every passing day.</p>
<p>And yes, I am stressed too. Aren&#8217;t we all&#8230; for the next big update to my iCatalog framework I&#8217;ve spent the last week to migrate everything to ARC. The whole project started out as one iPad app and over time the number of target has grown exponentially. We&#8217;re now developing some more advanced features but decided that these will be iOS 5 only. So &#8211; of course &#8211; I&#8217;m switching to ARC. And of course there is ShareKit which has no hope of being migrated to ARC soon, so I had to pack that into its own static library with ARC turned off. In the end I want the iCatalog project to be only for the core functionality. All the iCatalog apps should be in a different project so that I don&#8217;t have to mess with the dozens of targets for all the catalog apps any more. I am telling you this for two reasons: 1) as an excuse for not having a better show prepared. and 2) as a pointer that you might want to have reusable core functionality also in your own modules and sub- projects.</p>
<p>Oh, and I have another excuse: my MacBook Air is still being repaired. I suspect that the power regulator had a problem. Sometimes it wouldn&#8217;t charge, then it would. If you were lucky you could start it, but then it would shut down by itself after a short while. And then you couldn&#8217;t start it until you reset it with these secret key combinations. But fortunately I have AppleCare for it and so that should be fixed next week.</p>
<p>And now for some interesting news &#8230; yes there where a few&#8230;</p>
<p>TIOBE Software publishes their <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">Programming Community Index</a> every month. This is sort of a hit parade of programming languages somehow measured by an elaborate methodology that uses search engines to determine the relative importance of programming languages. In the current April report the top position went to C which overtook Java on second place compared to a year ago. C++ stayed put on third place. The big winner in the top 10 is Objective-C which moved from 8th place last April to number 4. Objective-C also became the &#8220;Language of the year&#8221; <a href="http://www.infoworld.com/d/application-development/apples-ios-strength-prompted-objective-c-languages-growth-in-2011-183609">in 2011</a> because it seems to be rising in these ranks like a rocket. All of us iOS and Mac developers using this for our favorite platform probably helps here quite a bit.</p>
<p>Google Currents launched internationally this month, after almost half a year being US-only. Will Kiefer, the iOS developer behind Google Currents, told me that they too make widespread use of UIWebViews for the main reason that their online publishing tool requires Javascript to run and that only the HTML5 CSS support in web views allows them to expose the customizability for their content partners. Will told me that to speed up image loading he replaced the normal NSURLCache mechanism with NSURLProtocol. This is faster because NSURLCache can only return one cached response at a time while NSURLProtocol can work concurrently. That&#8217;s definitely something worth looking into. I&#8217;m trying to get Will on the Cocoanetics podcast in one of the next episodes.</p>
<p>LLVM.org published in <a href="http://clang.llvm.org/docs/ObjectiveCLiterals.html">much greater detail</a> the new Objective-C literal syntax for NSNumbers and Containers. Users of Apple&#8217;s compiler will be able to start using these features with Apple LLVM Compiler 4.0. Users of open-source LLVM.org compiler releases can use these features starting with clang v3.1. The 4.0 compiler will be in Xcode 4.4 which is due out about the same time as OS X Mountain Lion sometime this summer. The good thing will be that since this is compile-time technology it will mean that we should be able to use the new Literal syntax also in older iOS versions.</p>
<p>Valve software, makers of Steam and amazing games like Half-Life, have <a href="http://cdn.flamehaus.com/Valve_Handbook_LowRes.pdf">published</a> a copy of their new employee handbook online. This manual is supposed to give new hires an overview of the Valve company philosophy. I recommend that you download this book and read it on your iPad because it is truly a piece of art. The manual in itself is a piece of art, it has beautiful illustrations and a ton of interesting content, even if you don&#8217;t plan to try to be hired by them.</p>
<p>Valve is nevertheless quite unusual in their philosophy. They don&#8217;t have a hierarchy or managers. Instead you are free to pick the projects that you would like to work  on. It&#8217;s like at Google where people have 20% for their own projects. Only at Valve this is 100%. I&#8217;m astonished that this can work, but I too will need to read the manual first before I can tell you how they do it. Quite inspirational!</p>
<p>Speaking of the value of employees: In the last quarter the profit per employee of Google, Apple and Sony were: $96,090 (33,464 employees) at Google, $215,200 (with 60,400 employees) at Apple and at Sony the average employee (of 168,200) lost the company $11,690. It&#8217;s interesting to see how Apple employees manage to make their company more than twice as much profit per person as Google employees. What is it that makes them so valuable? Possibly Apple selling boatloads of iOS devices?</p>
<p>David Smith published his <a href="http://david-smith.org/blog/2012/03/10/ios-5-dot-1-upgrade-stats/index.html#april15">latest 5.1 Upgrade stats</a> and he reports:</p>
<blockquote><p>Upgrades appear to have leveled off into the slow trickle phase. After the initial surge of upgrades (both OTA and otherwise) user adoption has transitioned into a more measured pace. Overall there is still a clear movement towards the newer OS variants. 82% of all users are now running some flavor of iOS 5.x.</p></blockquote>
<p>What&#8217;s interesting in these statistics is that there is even greater adoption of iOS 5 than it seems because the numbers are drawn down by laggards on various versions of the iPod Touch. On iPad you&#8217;ll find no less than 86% on iOS 5.0 or higher. On iPod Touches this is only 65%. My theory is that these iPod Touches are mostly in the hands of children which don&#8217;t care for a newer iOS versions while the games they want to play still support iOS 4.</p>
<p>David Smith concludes that these numbers are good enough for him to drop iOS 4 support in his next major updates.</p>
<p><a href="https://developer.apple.com/news/index.php">App Store Review Weather</a>: As of April 20th there was a 3% chance of raining on your New Apps, 1% of bad weather for App Updates.</p>
<p>Kickstarter Projects mentioned:</p>
<ul>
<li><a href="http://www.kickstarter.com/projects/1404403369/geode-from-icache">Geode from iCache!</a> &#8211; An iPhone case with build in e-ink display for dynamically displaying loyalty card barcodes plus on-the-fly programmable credit card</li>
<li><a href="http://www.kickstarter.com/projects/449163977/galileo-your-ios-in-motion">Galileo</a> &#8211; an remote-controllable robotic iPhone stand for panning and tilting</li>
<li><a href="http://www.kickstarter.com/projects/597507018/pebble-e-paper-watch-for-iphone-and-android">Pebble</a> &#8211; E-Paper Watch</li>
<li><a href="http://www.kickstarter.com/projects/66710809/double-fine-adventure">Double Fine Adventure</a> &#8211; previous record holder until the Pebble beat it</li>
<li><a href="http://www.kickstarter.com/projects/leisuresuitlarry/make-leisure-suit-larry-come-again">Make Leisure Suit Larry come again</a> &#8211; cutting it close to the $500,000 goal, Larry is dear to many but a bad influence for many more</li>
</ul>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6242&amp;md5=054563aa9a743c41dec3f286ae3c6fbe" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/podcast-34-be-excellent-and-valuable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.cocoanetics.com/files/Cocoanetics_034.mp3" length="14501721" type="audio/mpeg" />
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fpodcast-34-be-excellent-and-valuable%2F&amp;language=en_GB&amp;category=text&amp;title=Podcast+%2334+%26%238211%3B+%26%238220%3BBe+Excellent+And+Valuable%26%238221%3B&amp;description=Episode+34%2C+recorded+Saturday+April+21th%2C+2012+We+can+learn+about+cool+company+philosophy+from+the+Valve+employee+handbook%2C+Objective-C+is+creeping+up+to+C%2B%2B+as+the+world%26%238217%3Bs+almost+most...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>DTCoreText 1.0.1, Linker Flags and Rich Text News</title>
		<link>http://www.cocoanetics.com/2012/04/dtcoretext-1-0-1-linker-flags-and-rich-text-news/</link>
		<comments>http://www.cocoanetics.com/2012/04/dtcoretext-1-0-1-linker-flags-and-rich-text-news/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 09:08:24 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Updates]]></category>
		<category><![CDATA[DTCoreText]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6255</guid>
		<description><![CDATA[I reported a while ago that I was forced to tag the current state of the DTCoreText master repository as 1.0.0. The reason for this was that CocoaPods was starting to gain lots of momentum and several people wanted to use DTCoreText via a podspec. You can have podspecs point to the master branch as well, but then you never really know what you get. This can possibly cause many headaches especially in larger projects where you cannot track the state of each individual sub-project. Therefore it is generally recommended &#8211; if not required &#8211; to make use of tags in GitHub. &#160; Tags are like labels that you attach to the current state of a repository. You can create them simply by issuing the following command in the repository root folder. git tag &#34;1.0.1&#34; You can list the existing tags with: git tag -l There is an option on git push to have the tags also travel to the origin repository on GitHub: git push origin master --tags Once you&#8217;ve done that, GitHub provides snapshots of the tagged state as tar balls and zip files&#8230; though you probably don&#8217;t want to use these but rather have the project as a clone so that you can easily update it. DTCoreText News Amongst the fixes that made this maintenance release necessary where: Fixed Block-Retain-Cycle Fixed a second minor retain-cycle Workaround for Chinese Font cascade bug in iOS 5.x (radar://11262229) Workaround for a CoreText memory leak in iOS 4.3 (fixed in 5.0) Some Unit Testing corrections Updated Readme regarding necessary linker flags I finally got around to also filing a Radar for the cascade bug. The memory leak issue is fixed as of iOS 5, the problem there was that if you replaced the paragraph style attribute on an NSAttributedString with a new one, the previous entry would leak. I fixed that by simply removing the attribute first before calling addAttribute with the new style. The project has surpassed 1000 watchers on GitHub which tells me that it is definitely of use for many people. If you have any app making use of it, then please tell me about it as I like to feature your work. I especially love to receive testimonials like this one. The changes to the Readme reflect the outcome of research done by David Hoerl. The question was to determine which linker flags are really necessary when linking in DTCoreText &#8211; or any other static library that contains categories &#8211; into an app. Linker Flags Wisdom The linker in general tries to only link in code that is actually used. So if you have C-functions then their code will not end up in the final app binary if it is never being called. This does not work for Objective-C category extensions because of the dynamic nature of method resolution. Therefore you would generally use the -ObjC linker flag when dealing with static libraries that contain Objective-C code. Greg Parker from Apple who refers to himself as &#8220;Runtime Wrangler&#8221; explains it like this: -all_load and -force_load act at link time, not at load time. -all_load and -force_load tell the linker to link the entire static archive in the final executable, even if the linker thinks that parts of the archive are unused. When you link a traditional C static archive (.a file), any code from the archive that is never referenced in the final executable is simply omitted from the executable. So if you had a static archive with 999 functions you did not call and 1 function that you did call, your final executable would include only that one function. Objective-C categories break the C static archive model, because you want the Objective-C category to appear in the final executable even though there are no C symbol references to it from the executable. The best solution for Objective-C categories in static archives is the -ObjC linker option, which tells the linker that all Objective-C categories in the archives are &#8220;used&#8221; but to apply the usual reference algorithm for everything else in the archives. The -ObjC option is broken in some versions of the linker. For those cases the -force_load and -all_load options work. The final executable may be larger than necessary with those options, if there were classes or C functions that could have been omitted by the linker. If you have multiple archives and only some of them have Objective-C code then -force_load may generate smaller output than -all_load. On iOS you&#8217;d typically only link in libraries that you need, as opposed to traditional C or C++ where you&#8217;d often link in large static libraries that are collections of utility methods. So in the case where the libDTCoreText.a is the only static library should be  no difference between force_load and all_load at all. Personally I prefer the [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/dtcoretext-1-0-1-linker-flags-and-rich-text-news/"></g:plusone></div><p>I reported a while ago that I was forced to tag the current state of the DTCoreText master repository as <a title="DTRichTextEditor / DTCoreText News" href="http://www.cocoanetics.com/2012/02/dtrichtexteditor-dtcoretext-news/">1.0.0</a>. The reason for this was that CocoaPods was starting to gain lots of momentum and several people wanted to use DTCoreText via a podspec.</p>
<p>You can have podspecs point to the master branch as well, but then you never really know what you get. This can possibly cause many headaches especially in larger projects where you cannot track the state of each individual sub-project.</p>
<p>Therefore it is generally recommended &#8211; if not required &#8211; to make use of tags in GitHub.</p>
<p><span id="more-6255"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>Tags are like labels that you attach to the current state of a repository. You can create them simply by issuing the following command in the repository root folder.</p>

<div class="wp_codebox"><table><tr id="p625573"><td class="code" id="p6255code73"><pre class="objc" style="font-family:monospace;">git tag <span style="color: #bf1d1a;">&quot;1.0.1&quot;</span></pre></td></tr></table></div>

<p>You can list the existing tags with:</p>

<div class="wp_codebox"><table><tr id="p625574"><td class="code" id="p6255code74"><pre class="objc" style="font-family:monospace;">git tag <span style="color: #002200;">-</span>l</pre></td></tr></table></div>

<p>There is an option on git push to have the tags also travel to the origin repository on GitHub:</p>

<div class="wp_codebox"><table><tr id="p625575"><td class="code" id="p6255code75"><pre class="objc" style="font-family:monospace;">git push origin master <span style="color: #002200;">--</span>tags</pre></td></tr></table></div>

<p>Once you&#8217;ve done that, GitHub provides snapshots of the tagged state as tar balls and zip files&#8230; though you probably don&#8217;t want to use these but rather have the project as a clone so that you can easily update it.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-17-um-9.59.15-AM.png"><img class="alignnone size-full wp-image-6256" title="Tags on GitHub" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-17-um-9.59.15-AM.png" alt="" width="341" height="371" /></a></p>
<h3>DTCoreText News</h3>
<p>Amongst the fixes that made this maintenance release necessary where:</p>
<ul>
<li>Fixed <a title="Block Retain Loop" href="http://www.cocoanetics.com/2012/03/block-retain-loop/">Block-Retain-Cycle</a></li>
<li>Fixed a second minor retain-cycle</li>
<li>Workaround for Chinese Font cascade bug in iOS 5.x (<a href="http://openradar.appspot.com/radar?id=1647415">radar://11262229</a>)</li>
<li>Workaround for a CoreText memory leak in iOS 4.3 (fixed in 5.0)</li>
<li>Some Unit Testing corrections</li>
<li>Updated Readme regarding necessary linker flags</li>
</ul>
<p>I finally got around to also filing a Radar for the cascade bug. The memory leak issue is fixed as of iOS 5, the problem there was that if you replaced the paragraph style attribute on an NSAttributedString with a new one, the previous entry would leak. I fixed that by simply removing the attribute first before calling addAttribute with the new style.</p>
<p>The project has <a href="https://github.com/Cocoanetics/DTCoreText/watchers">surpassed 1000 watchers</a> on GitHub which tells me that it is definitely of use for many people. If you have any app making use of it, then please tell me about it as I like to feature your work. I especially love to receive testimonials <a title="DTCoreText Feedback" href="http://www.cocoanetics.com/2012/03/dtcoretext-feedback/">like this one</a>.</p>
<p>The changes to the Readme reflect the outcome of research done by David Hoerl. The question was to determine which linker flags are really necessary when linking in DTCoreText &#8211; or any other static library that contains categories &#8211; into an app.</p>
<h3>Linker Flags Wisdom</h3>
<p>The linker in general tries to only link in code that is actually used. So if you have C-functions then their code will not end up in the final app binary if it is never being called. This does not work for Objective-C category extensions because of the dynamic nature of method resolution.</p>
<p>Therefore you would generally use the <strong>-ObjC</strong> linker flag when dealing with static libraries that contain Objective-C code.</p>
<p>Greg Parker from Apple who refers to himself as &#8220;Runtime Wrangler&#8221; <a href="http://osdir.com/ml/general/2012-04/msg28235.html">explains</a> it like this:</p>
<blockquote><p>-all_load and -force_load <strong>act at link time</strong>, not at load time. -all_load and<br />
-force_load tell the linker to link the entire static archive in the final<br />
executable, even if the linker thinks that parts of the archive are unused.</p>
<p>When you link a traditional C static archive (.a file), any code from the<br />
archive that is never referenced in the final executable is simply omitted from<br />
the executable. So if you had a static archive with 999 functions you did not<br />
call and 1 function that you did call, your final executable would include only<br />
that one function.</p>
<p>Objective-C categories break the C static archive model, because you want the<br />
Objective-C category to appear in the final executable even though there are no<br />
C symbol references to it from the executable.</p>
<p>The <strong>best solution for Objective-C categories in static archives is the -ObjC</strong><br />
<strong> linker option</strong>, which tells the linker that all Objective-C categories in the<br />
archives are &#8220;used&#8221; but to apply the usual reference algorithm for everything<br />
else in the archives.</p>
<p>The -ObjC option is <strong>broken in some versions of the linker</strong>. For those cases the<br />
-force_load and -all_load options work. The final executable may be larger than<br />
necessary with those options, if there were classes or C functions that could<br />
have been omitted by the linker. If you have multiple archives and only some of<br />
them have Objective-C code then -force_load may generate smaller output than<br />
-all_load.</p></blockquote>
<p>On iOS you&#8217;d typically only link in libraries that you need, as opposed to traditional C or C++ where you&#8217;d often link in large static libraries that are collections of utility methods. So in the case where the libDTCoreText.a is the only static library should be  no difference between force_load and all_load at all.</p>
<p>Personally I prefer the simplest approach which is to first try to get by with only -ObjC and if I get unrecognized selector crashes to additionally add -force_load because there I don&#8217;t need to know or specify the path to the specific library.</p>
<h3>DTRichTextEditor</h3>
<p>I&#8217;ve streamed all the 1.0.1 updates also into DTRichTextEditor which uses DTCoreText for display of rich text. Changes there include:</p>
<ul>
<li>Support Left, Center, Right and Justified toggling of paragraphs</li>
<li>Preliminary work on supporting lists</li>
</ul>
<p>I love to get feedback from people who are actually using the editor in shipping apps. The most prominent one is Dootrix who made the <a href="http://www.simpl.com/">Simpl iPad app</a>. I <a title="Podcast #33 – “Rich Texting”" href="http://www.cocoanetics.com/2012/04/podcast-33-rich-texting/">interviewed the maker</a> on my podcast, if you haven&#8217;t done so I urge you to listen to it as I think it was one of the most enlightening conversations I ever had on air.</p>
<p><a href="http://www.cocoanetics.com/files/mzl.qmfvnljn.480x480-75.jpg"><img class="alignnone size-full wp-image-6257" title="Simpl app using DTRichTextEditor" src="http://www.cocoanetics.com/files/mzl.qmfvnljn.480x480-75.jpg" alt="" width="480" height="351" /></a></p>
<p>I keep getting requests for a ways to test the editor component before purchasing it. Also the work on lists as well as some feature requests are still open for the editor.</p>
<p>Unfortunately I won&#8217;t have any time to devote to these requests as we are in &#8220;crunch time&#8221; for a major project of maximum importance for the next two weeks. Therefore I ask for some patience.</p>
<h3>The Future</h3>
<p>I&#8217;m not making very much money from selling licenses. Only enough to justify it as a hobby. I might be forced to dramatically raise the price in the near future. So if you are thinking of buying then better do so now, because you then will have access to my Subversion repository and get the benefit of all future updates.</p>
<p>On the above mentioned podcast episode I also discussed what my thoughts where related to the future of rich text editing on iOS.</p>
<p>I am happy if Apple takes on more of the burden that DTCoreText and DTRichTextEditor are currently carrying. It is astonishing that they truly believe that people would use contentEditable UIWebViews for that task. As iPads become equal-partners in content creation this is an essential platform feature.</p>
<p>There are two levels that I can see Apple move forward on:</p>
<ul>
<li>Add the missing protocols and interfaces for interacting with selections and the magnifying glass &#8211; you would still have to create your own editor but at least you could do way more easily</li>
<li>Enhance UITextView &#8211; which is using <a href="http://code.google.com/p/iphone-dev/source/browse/branches/include-1.2-sdk/include/UIKit/UITextView.h?r=266">WebKit under the hood</a> already &#8211; to be editable. Or alternatively create a totally new Rich Text Editing View.</li>
</ul>
<p>Either way I will still have a market and and audience while people support 4.3 and above, or 5.0 and above when 6.0 finally ships. I would predict the former and not bet on the latter.</p>
<p>To cut a long story short: progress is being made and patience is required.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6255&amp;md5=06938ab9e3ec6f3c8f79b6abe64f38f8" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/dtcoretext-1-0-1-linker-flags-and-rich-text-news/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fdtcoretext-1-0-1-linker-flags-and-rich-text-news%2F&amp;language=en_GB&amp;category=text&amp;title=DTCoreText+1.0.1%2C+Linker+Flags+and+Rich+Text+News&amp;description=I+reported+a+while+ago+that+I+was+forced+to+tag+the+current+state+of+the+DTCoreText+master+repository+as+1.0.0.+The+reason+for+this+was+that+CocoaPods+was+starting...&amp;tags=DTCoreText%2Cblog" type="text/html" />
	</item>
		<item>
		<title>Podcast #33 &#8211; &#8220;Rich Texting&#8221;</title>
		<link>http://www.cocoanetics.com/2012/04/podcast-33-rich-texting/</link>
		<comments>http://www.cocoanetics.com/2012/04/podcast-33-rich-texting/#comments</comments>
		<pubDate>Sat, 14 Apr 2012 17:01:52 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6223</guid>
		<description><![CDATA[Episode 33, recorded April 14th, 2012 Everybody still waiting for WWDC. My MacBook Air misbehaves and thus I have no show prepared. But Kevin Smith from Dootrix saves us this week from having no show: we chat about Rich Text and the Simpl app which they made. &#160; Show Notes Kevin Smith is co-founder of Dootrix Ltd, a company that develops mobile apps for business and enterprise clients. We chat about rich text, display and editing and what went into the Simpl app they created for Simpl. And its all super-simpl, really&#8230; Links: Company website: www.dootrix.com Blog: www.in-traction.com The Simpl App: www.simpl.com Apps for taking only iPad to clients: iMockup Blueprint SketchBook Mobile Feedback I love to hear from you, you can email me at oliver@cocoanetics.com or tweet me @cocoanetics. If you want to give me audio feedback or have some interesting comment for me to play on the show please call my Google Voice mailbox:  (415) 860-4324]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/podcast-33-rich-texting/"></g:plusone></div><p>Episode 33, recorded April 14th, 2012</p>
<p>Everybody still waiting for WWDC. My MacBook Air misbehaves and thus I have no show prepared. But Kevin Smith from Dootrix saves us this week from having no show: we chat about Rich Text and the Simpl app which they made.</p>

<p><span id="more-6223"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>Show Notes</h3>
<p><a href="http://twitter.com/kevatron">Kevin Smith</a> is co-founder of Dootrix Ltd, a company that develops mobile apps for business and enterprise clients. We chat about rich text, display and editing and what went into the Simpl app they created for Simpl. And its all super-simpl, really&#8230; <img src='http://www.cocoanetics.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Links:</p>
<ul>
<li>Company website: <a href="http://www.dootrix.com">www.dootrix.com</a></li>
<li>Blog: <a href="http://www.in-traction.com">www.in-traction.com</a></li>
<li>The Simpl App: <a href="http://www.simpl.com">www.simpl.com</a></li>
</ul>
<p>Apps for taking only iPad to clients:</p>
<ul>
<li><a href="http://itunes.apple.com/at/app/imockups-for-ipad/id364885913?mt=8">iMockup</a></li>
<li><a href="http://itunes.apple.com/at/app/blueprint/id405203705?mt=8">Blueprint</a></li>
<li><a href="http://itunes.apple.com/at/app/sketchbook-mobile/id327375467?mt=8">SketchBook Mobile</a></li>
</ul>
<h3>Feedback</h3>
<p>I love to hear from you, you can email me at oliver@cocoanetics.com or tweet me @cocoanetics. If you want to give me audio feedback or have some interesting comment for me to play on the show please call my Google Voice mailbox:  <strong>(415) 860-4324</strong></p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6223&amp;md5=de3f740c9142d1a55ca687ebf215a3c2" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/podcast-33-rich-texting/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://www.cocoanetics.com/files/Cocoanetics_033.mp3" length="53924488" type="audio/mpeg" />
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fpodcast-33-rich-texting%2F&amp;language=en_GB&amp;category=text&amp;title=Podcast+%2333+%26%238211%3B+%26%238220%3BRich+Texting%26%238221%3B&amp;description=Episode+33%2C+recorded+April+14th%2C+2012+Everybody+still+waiting+for+WWDC.+My+MacBook+Air+misbehaves+and+thus+I+have+no+show+prepared.+But+Kevin+Smith+from+Dootrix+saves+us+this...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Containing ViewControllers</title>
		<link>http://www.cocoanetics.com/2012/04/containing-viewcontrollers/</link>
		<comments>http://www.cocoanetics.com/2012/04/containing-viewcontrollers/#comments</comments>
		<pubDate>Sat, 14 Apr 2012 13:44:59 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6225</guid>
		<description><![CDATA[For a project that I am currently working on I needed to implement a custom container view controller. I was feeling my way forward in the dark for the most part because this does not seem to be a widely used technique. Developers &#8211; understandably &#8211; favor reusing and skinning existing view controllers over creating new containers. However there are some scenarios where you should prefer to make your own container because it greatly simplifies your code over trying to bend a UINavigationController or UITabBarController to your will. Do you remember the times when those two where the only two containers available? I distinctly remember using a UINavigationController with hidden nav bar as a view controller to contain multiple full views. And you probably had do do your own view juggling and animations because for the most part the standard transitions would be useless. Fortunately we can no file this as a fond memory of the past and move on to implementing our own containers. &#160; The first thing to wrap your head around is the notion that besides a hierarchy of views you now also have to have a consistent hierarchy of view controllers. Before iOS 5 people would often create a new view controller and then slap this VC&#8217;s view into an existing view hierarchy. Now more! Nowadays you never would resort to this. Instead you use the mechanisms afforded by UIViewController to add and remove child view controllers. Another notion is that we&#8217;ve trained ourselves to think of view controllers as being responsible for one entire full screen, think of the sub view controllers of a tab bar controller. But ever since UISplitViewController which arrived with the iPad this is no longer the true mantra. Viewcontrollers are supposed to manage a coherent region on the screen, that can be the entire screen for lack of space on an iPhone, but it can also be a content bar at one of the sides of the screen. Like UISplitViewController which has two sub-viewcontrollers, one for the left (&#8220;master&#8221;) panel and one for the right (&#8220;detail&#8221;) panel. UIViewController provides two methods to add a view controller as a child and to remove it later. Those are part of the &#8220;UIContainerViewControllerProtectedMethods&#8221; category extension for UIViewController: @interface UIViewController &#40;UIContainerViewControllerProtectedMethods&#41; &#160; - &#40;void&#41;addChildViewController:&#40;UIViewController *&#41;childController; - &#40;void&#41;removeFromParentViewController; &#160; @end These two methods do exactly what their names suggest. Though what&#8217;s not quite obvious is how you are supposed to use them. And if and how you should combine these with addSubview and removeFromSuperview. Hence this exploration. Note: All this assumes we use ARC. According to the docs it is up to us to define the kinds of relationships we want to model. Be it only a single VC visible at the time like nav controllers, or multiple that can be reached through tabs. Or even multiple VCs that are sort of like pages. There are three possible things that you want to be able to do with your sub-viewcontrollers that have slightly different semantics: Add it to your container Remove it from your container Transition to another view controller (i.e. add the new and remove the old) For any of these you also want to be be assured that the 4 view delegate methods get properly called, as well as the new 2 delegate methods that fire before and after a VC moved to a new parent. Note that a parent of nil means that it was removed. Why is this attention to the delegate messaging necessary? You probably use the view(Did&#124;Will)(A&#124;Disa)pear methods to do some last setup or teardown and so you are interested that they get properly called. And also there is an ugly warning in the console about unbalanced messages if you get something wrong here. We&#8217;ll dive into greater detail with a sample. Let&#8217;s say we want to get an effect similar to a tabbed view controller. i.e. we have an array of view controllers and we want to switch between these. Since this container VC will be our app&#8217;s root view controller we want to show the first sub-VC when it shows. Basic Setup Let&#8217;s put the necessary bare bones IVARs in the implementation because we only need to have access to these inside our own ContainerViewController. @implementation ContainerViewController &#123; NSArray *_subViewControllers; UIViewController *_selectedViewController; UIView *_containerView; &#125; The subVCs will be a static array of view controllers that the developer can set. The selected VC will hold a reference to the currently showing VC and the container view will be the area where we want our sub VC&#8217;s view to be positioned. Let&#8217;s start by setting up the container view in the container&#8217;s loadView: - &#40;void&#41;loadView &#123; // set up the base view CGRect frame = &#91;&#91;UIScreen mainScreen&#93; applicationFrame&#93;; UIView *view = &#91;&#91;UIView alloc&#93; initWithFrame:frame&#93;; view.autoresizingMask = UIViewAutoresizingFlexibleWidth &#124; [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/containing-viewcontrollers/"></g:plusone></div><p>For a project that I am currently working on I needed to implement a custom container view controller. I was feeling my way forward in the dark for the most part because this does not seem to be a widely used technique. Developers &#8211; understandably &#8211; favor reusing and skinning existing view controllers over creating new containers.</p>
<p>However there are some scenarios where you should prefer to make your own container because it greatly simplifies your code over trying to bend a UINavigationController or UITabBarController to your will. Do you remember the times when those two where the only two containers available?</p>
<p>I distinctly remember using a UINavigationController with hidden nav bar as a view controller to contain multiple full views. And you probably had do do your own view juggling and animations because for the most part the standard transitions would be useless. Fortunately we can no file this as a fond memory of the past and move on to implementing our own containers.</p>
<p><span id="more-6225"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>The first thing to wrap your head around is the notion that besides a hierarchy of views you now also have to have a consistent hierarchy of view controllers. Before iOS 5 people would often create a new view controller and then slap this VC&#8217;s view into an existing view hierarchy. Now more!</p>
<p>Nowadays you never would resort to this. Instead you use the mechanisms afforded by UIViewController to add and remove child view controllers.</p>
<p>Another notion is that we&#8217;ve trained ourselves to think of view controllers as being responsible for one entire full screen, think of the sub view controllers of a tab bar controller. But ever since UISplitViewController which arrived with the iPad this is no longer the true mantra. Viewcontrollers are supposed to manage a coherent region on the screen, that can be the entire screen for lack of space on an iPhone, but it can also be a content bar at one of the sides of the screen. Like UISplitViewController which has two sub-viewcontrollers, one for the left (&#8220;master&#8221;) panel and one for the right (&#8220;detail&#8221;) panel.</p>
<p>UIViewController provides two methods to add a view controller as a child and to remove it later. Those are part of the &#8220;UIContainerViewControllerProtectedMethods&#8221; category extension for UIViewController:</p>

<div class="wp_codebox"><table><tr id="p622590"><td class="code" id="p6225code90"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> UIViewController <span style="color: #002200;">&#40;</span>UIContainerViewControllerProtectedMethods<span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>addChildViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>childController;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>removeFromParentViewController;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>These two methods do exactly what their names suggest. Though what&#8217;s not quite obvious is how you are supposed to use them. And if and how you should combine these with addSubview and removeFromSuperview. Hence this exploration. Note: All this assumes we use ARC.</p>
<p>According to the docs it is up to us to define the kinds of relationships we want to model. Be it only a single VC visible at the time like nav controllers, or multiple that can be reached through tabs. Or even multiple VCs that are sort of like pages. </p>
<p>There are three possible things that you want to be able to do with your sub-viewcontrollers that have slightly different semantics:</p>
<ul>
<li><strong>Add</strong> it to your container</li>
<li><strong>Remove</strong> it from your container</li>
<li><strong>Transition</strong> to another view controller (i.e. add the new and remove the old)</li>
</ul>
<p>For any of these you also want to be be assured that the 4 view delegate methods get properly called, as well as the new 2 delegate methods that fire before and after a VC moved to a new parent. Note that a parent of nil means that it was removed.</p>
<p>Why is this attention to the delegate messaging necessary? You probably use the view(Did|Will)(A|Disa)pear methods to do some last setup or teardown and so you are interested that they get properly called. And also there is an ugly warning in the console about unbalanced messages if you get something wrong here.</p>
<p>We&#8217;ll dive into greater detail with a sample. Let&#8217;s say we want to get an effect similar to a tabbed view controller. i.e. we have an array of view controllers and we want to switch between these. Since this container VC will be our app&#8217;s root view controller we want to show the first sub-VC when it shows.</p>
<h3>Basic Setup</h3>
<p>Let&#8217;s put the necessary bare bones IVARs in the implementation because we only need to have access to these inside our own ContainerViewController.</p>

<div class="wp_codebox"><table><tr id="p622591"><td class="code" id="p6225code91"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@implementation</span> ContainerViewController
<span style="color: #002200;">&#123;</span>
	<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span>_subViewControllers;
	UIViewController <span style="color: #002200;">*</span>_selectedViewController;
	UIView <span style="color: #002200;">*</span>_containerView;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The subVCs will be a static array of view controllers that the developer can set. The selected VC will hold a reference to the currently showing VC and the container view will be the area where we want our sub VC&#8217;s view to be positioned. Let&#8217;s start by setting up the container view in the container&#8217;s loadView:</p>

<div class="wp_codebox"><table><tr id="p622592"><td class="code" id="p6225code92"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>loadView
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// set up the base view</span>
	CGRect frame <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIScreen mainScreen<span style="color: #002200;">&#93;</span> applicationFrame<span style="color: #002200;">&#93;</span>;
	UIView <span style="color: #002200;">*</span>view <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIView alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>frame<span style="color: #002200;">&#93;</span>;
	view.autoresizingMask <span style="color: #002200;">=</span> UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	view.backgroundColor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIColor blueColor<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// set up content view a bit inset</span>
	frame <span style="color: #002200;">=</span> CGRectInset<span style="color: #002200;">&#40;</span>view.bounds, <span style="color: #2400d9;">0</span>, <span style="color: #2400d9;">100</span><span style="color: #002200;">&#41;</span>;
	_containerView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIView alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>frame<span style="color: #002200;">&#93;</span>;
	_containerView.backgroundColor <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>UIColor redColor<span style="color: #002200;">&#93;</span>;
	_containerView.autoresizingMask <span style="color: #002200;">=</span> UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	<span style="color: #002200;">&#91;</span>view addSubview<span style="color: #002200;">:</span>_containerView<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// from here on the container is automatically adjusting to the orientation</span>
	self.view <span style="color: #002200;">=</span> view;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>I&#8217;ve colored the main view blue and the container view red for clarity. The sub-VCs will go in the red area and be automatically resized if we rotate the device.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-14-um-2.10.24-PM.png"><img src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-14-um-2.10.24-PM-232x300.png" alt="" title="Basic Setup of Container" width="232" height="300" class="alignnone size-medium wp-image-6226" /></a></p>
<p>The integration in the app delegate is a mere formality, add the import for the header, allocate an instance and set it as root VC.</p>

<div class="wp_codebox"><table><tr id="p622593"><td class="code" id="p6225code93"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>application<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application didFinishLaunchingWithOptions<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>launchOptions
<span style="color: #002200;">&#123;</span>
    self.window <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIWindow alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIScreen mainScreen<span style="color: #002200;">&#93;</span> bounds<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	ContainerViewController <span style="color: #002200;">*</span>container <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>ContainerViewController alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;	
 	self.window.rootViewController <span style="color: #002200;">=</span> container;
&nbsp;
    <span style="color: #002200;">&#91;</span>self.window makeKeyAndVisible<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Next we need a couple of view controllers to play the role of the sub-VCs. Let&#8217;s create a simple UIViewController subclass that has a UILabel as it&#8217;s main view, so that we can display something there to tell them apart. Do avoid overcomplicating things for this example we simple take the view&#8217;s own description in there. This way we see if the display changes.</p>

<div class="wp_codebox"><table><tr id="p622594"><td class="code" id="p6225code94"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>loadView
<span style="color: #002200;">&#123;</span>
	<span style="color: #11740a; font-style: italic;">// set up the base view</span>
	CGRect frame <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIScreen mainScreen<span style="color: #002200;">&#93;</span> applicationFrame<span style="color: #002200;">&#93;</span>;
	UILabel <span style="color: #002200;">*</span>label <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UILabel alloc<span style="color: #002200;">&#93;</span> initWithFrame<span style="color: #002200;">:</span>frame<span style="color: #002200;">&#93;</span>;
	label.numberOfLines <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; <span style="color: #11740a; font-style: italic;">// multiline</span>
	label.textAlignment <span style="color: #002200;">=</span> UITextAlignmentCenter;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// let's just have this view description</span>
	label.text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self description<span style="color: #002200;">&#93;</span>;
	self.view <span style="color: #002200;">=</span> label;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>I bet you never before had a view controller which consisted only of a UILabel. For Science! <img src='http://www.cocoanetics.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Adding</h3>
<p>Next we need to put a couple of these PageViewControllers into an array and have a method that allows us to set this array into our container. Let&#8217;s assume that you know how to create a property for the subViewControllers. In the app delegate we have these additional lines:</p>

<div class="wp_codebox"><table><tr id="p622595"><td class="code" id="p6225code95"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// make an array of 5 PageVCs</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> <span style="color: #002200;">*</span>tmpArray <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/"><span style="color: #400080;">NSMutableArray</span></a> array<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span> i<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>; i&lt;<span style="color: #2400d9;">5</span>; i<span style="color: #002200;">++</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	PageViewController <span style="color: #002200;">*</span>page <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PageViewController alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>tmpArray addObject<span style="color: #002200;">:</span>page<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// set these as sub VCs</span>
<span style="color: #002200;">&#91;</span>container setSubViewControllers<span style="color: #002200;">:</span>tmpArray<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>So much for basic setup. Now let&#8217;s override the setter for the sub VCs to select the VC at index 0 and present it. Though we cannot present it in the setter, because the view might not have been loaded yet and so our _containerView IVAR is still nil.</p>

<div class="wp_codebox"><table><tr id="p622596"><td class="code" id="p6225code96"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setSubViewControllers<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/"><span style="color: #400080;">NSArray</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>subViewControllers
<span style="color: #002200;">&#123;</span>
	_subViewControllers <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>subViewControllers copy<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_selectedViewController<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #11740a; font-style: italic;">// TODO: remove previous VC</span>
	<span style="color: #002200;">&#125;</span>
&nbsp;
	_selectedViewController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>subViewControllers objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// cannot add here because the view might not have been loaded yet</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@synthesize</span> subViewControllers <span style="color: #002200;">=</span> _subViewControllers;</pre></td></tr></table></div>

<p>Instead we do it at the latest possible moment, that would be in the viewWillAppear because here we are guaranteed that the loadView has taken place already. A nice lazy thing, if we find that the selected VC already has self as the parent then there&#8217;s nothing to do.</p>

<div class="wp_codebox"><table><tr id="p622597"><td class="code" id="p6225code97"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewWillAppear<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>animated
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>super viewWillAppear<span style="color: #002200;">:</span>animated<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_selectedViewController.parentViewController <span style="color: #002200;">==</span> self<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #11740a; font-style: italic;">// nowthing to do</span>
		<span style="color: #a61390;">return</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// adjust the frame to fit in the container view</span>
	_selectedViewController.view.frame <span style="color: #002200;">=</span> _containerView.bounds;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// make sure that it resizes on rotation automatically</span>
	_selectedViewController.view.autoresizingMask <span style="color: #002200;">=</span> _containerView.autoresizingMask;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// add as child VC</span>
	<span style="color: #002200;">&#91;</span>self addChildViewController<span style="color: #002200;">:</span>_selectedViewController<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// add it to container view, calls willMoveToParentViewController for us</span>
	<span style="color: #002200;">&#91;</span>_containerView addSubview<span style="color: #002200;">:</span>_selectedViewController.view<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// notify it that move is done</span>
	<span style="color: #002200;">&#91;</span>_selectedViewController didMoveToParentViewController<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The above shown sequence takes care of calling the viewWillAppear, viewDidAppear, willMoveToParentViewController and didMoveToParentViewController. Notice that all but the last are done for you automatically, but for some strange reason the didMove is not. So we have to do that manually. Upon starting our Demo we now see the VC at index 0.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-14-um-2.41.09-PM.png"><img src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-14-um-2.41.09-PM-232x300.png" alt="" title="Page VC presented" width="232" height="300" class="alignnone size-medium wp-image-6229" /></a></p>
<p>Next we add the capability to transition from one VC to the next. </p>
<h3>Transitioning</h3>
<p>To move between the child VCs we&#8217;ll add a swipe gesture recognizer to our container. If we swipe left we want to go to the VC with a lower index in the array. If we swipe right we want to go higher. No wrapping. In loadView we add:</p>

<div class="wp_codebox"><table><tr id="p622598"><td class="code" id="p6225code98"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// add gesture support</span>
UISwipeGestureRecognizer <span style="color: #002200;">*</span>swipeLeft <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UISwipeGestureRecognizer alloc<span style="color: #002200;">&#93;</span> initWithTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>swipeLeft<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
swipeLeft.direction <span style="color: #002200;">=</span> UISwipeGestureRecognizerDirectionLeft;
<span style="color: #002200;">&#91;</span>view addGestureRecognizer<span style="color: #002200;">:</span>swipeLeft<span style="color: #002200;">&#93;</span>;
&nbsp;
UISwipeGestureRecognizer <span style="color: #002200;">*</span>swipeRight <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UISwipeGestureRecognizer alloc<span style="color: #002200;">&#93;</span> initWithTarget<span style="color: #002200;">:</span>self action<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>swipeRight<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
swipeRight.direction <span style="color: #002200;">=</span> UISwipeGestureRecognizerDirectionRight;
<span style="color: #002200;">&#91;</span>view addGestureRecognizer<span style="color: #002200;">:</span>swipeRight<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>And the implementation of swipe is as follows. For simplicity&#8217;s sake we use two separate gesture recognizers because Apple does not provide an easy way to determine the swipe direction if you combine to directions.</p>

<div class="wp_codebox"><table><tr id="p622599"><td class="code" id="p6225code99"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>swipeLeft<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UISwipeGestureRecognizer <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>gesture
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>gesture.state <span style="color: #002200;">==</span> UIGestureRecognizerStateRecognized<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		NSInteger index <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_subViewControllers indexOfObject<span style="color: #002200;">:</span>_selectedViewController<span style="color: #002200;">&#93;</span>;
		index <span style="color: #002200;">=</span> MIN<span style="color: #002200;">&#40;</span>index<span style="color: #002200;">+</span><span style="color: #2400d9;">1</span>, <span style="color: #002200;">&#91;</span>_subViewControllers count<span style="color: #002200;">&#93;</span><span style="color: #002200;">-</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#41;</span>;
&nbsp;
		UIViewController <span style="color: #002200;">*</span>newSubViewController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_subViewControllers objectAtIndex<span style="color: #002200;">:</span>index<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #002200;">&#91;</span>self transitionFromViewController<span style="color: #002200;">:</span>_selectedViewController toViewController<span style="color: #002200;">:</span>newSubViewController<span style="color: #002200;">&#93;</span>; 
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>swipeRight<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UISwipeGestureRecognizer <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>gesture
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>gesture.state <span style="color: #002200;">==</span> UIGestureRecognizerStateRecognized<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		NSInteger index <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_subViewControllers indexOfObject<span style="color: #002200;">:</span>_selectedViewController<span style="color: #002200;">&#93;</span>;
		index <span style="color: #002200;">=</span> MAX<span style="color: #002200;">&#40;</span>index<span style="color: #002200;">-</span><span style="color: #2400d9;">1</span>, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
&nbsp;
		UIViewController <span style="color: #002200;">*</span>newSubViewController <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>_subViewControllers objectAtIndex<span style="color: #002200;">:</span>index<span style="color: #002200;">&#93;</span>;
&nbsp;
		<span style="color: #002200;">&#91;</span>self transitionFromViewController<span style="color: #002200;">:</span>_selectedViewController toViewController<span style="color: #002200;">:</span>newSubViewController<span style="color: #002200;">&#93;</span>; 
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The logic to transition from one VC to another we package in transitionFromViewController:toViewController:. This is the really interesting part. There is a convenient method that again takes care of most of the boring work of adding and removing views. And again some non-obvious additional messaging is necessary to get it perfect.</p>

<div class="wp_codebox"><table><tr id="p6225100"><td class="code" id="p6225code100"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>transitionFromViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>fromViewController toViewController<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>toViewController
<span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>fromViewController <span style="color: #002200;">==</span> toViewController<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #11740a; font-style: italic;">// cannot transition to same</span>
		<span style="color: #a61390;">return</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #11740a; font-style: italic;">// animation setup</span>
	toViewController.view.frame <span style="color: #002200;">=</span> _containerView.bounds;
	toViewController.view.autoresizingMask <span style="color: #002200;">=</span> _containerView.autoresizingMask;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// notify</span>
	<span style="color: #002200;">&#91;</span>fromViewController willMoveToParentViewController<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>self addChildViewController<span style="color: #002200;">:</span>toViewController<span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">// transition</span>
	<span style="color: #002200;">&#91;</span>self transitionFromViewController<span style="color: #002200;">:</span>fromViewController
					  toViewController<span style="color: #002200;">:</span>toViewController
							  duration<span style="color: #002200;">:</span><span style="color: #2400d9;">1.0</span>
							   options<span style="color: #002200;">:</span>UIViewAnimationOptionTransitionCurlDown
							animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
							<span style="color: #002200;">&#125;</span>
							completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span> finished<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
								<span style="color: #002200;">&#91;</span>toViewController didMoveToParentViewController<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
								<span style="color: #002200;">&#91;</span>fromViewController removeFromParentViewController<span style="color: #002200;">&#93;</span>;
							<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>And with that we have our transitions in the can.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-14-um-3.27.33-PM.png"><img src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-14-um-3.27.33-PM-232x300.png" alt="" title="Transition working" width="232" height="300" class="alignnone size-medium wp-image-6234" /></a></p>
<p>You have a number of UIViewAnimationOptionTransition-s available, but you don&#8217;t have to settle for these. You can also pass 0 for the options and instead provide all animations you like the two views to execute in the animations block. </p>
<p>Before I discovered is method I was using the previous method of animating the views. Though this has a side-effect that we might not like in this case. Typically you want the &#8220;will&#8221; delegate methods to fire before the transition and the &#8220;did&#8221; to follow afterwards. If you animate the views yourself then iOS 5 will take care of sending these messages for you but it does so together. This looses us the ability to differentiate between stuff we want to do before and after the appearing and disappearing of the view controller.</p>
<h3>Conclusion</h3>
<p>It took me quite a bit of experimenting to also get all the messaging happening and equally balanced. The above sample has that working as it should.</p>
<p>But once you do figure out the two techniques outlined in this article you are on the road to implement your own view controller containment like you never did anything else. </p>
<p>One thing that I wasn&#8217;t able to figure out so far is why the transition method always adds the new view controller&#8217;s view to the container view controller&#8217;s main view. This simplifes the process somewhat because you don&#8217;t have to know at which stage in the transition it is ok to add and remove the views. But at the same time you might have a situation where you don&#8217;t want the animation to occur over the entire area of the container view controller. </p>
<p>For this scenario I can only think of covering up the parts with extra sub views. Or we could stack multiple container view controllers and have one to only cover the region where where have the container view. This could then clip its subviews and thus be only care for this area.</p>
<p>The main advantage of any kind of view controller containment is that rotation messages (should|will|did) reach the lowest leaves of your view controller tree. Unless you disable that by means of overriding automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers and returning NO.</p>
<p>But who would really want that when we have waited for so long for public API to have these being forwarded? Working with view controller containers I get a feeling that they greatly simplified creating complex user interfaces consisting of multiple parts.</p>
<p>The project for this tutorial is in <a href="https://github.com/Cocoanetics/Examples">my Examples GitHub repository</a>.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6225&amp;md5=46459a7a8ca486564795a0f703b323b6" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/containing-viewcontrollers/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fcontaining-viewcontrollers%2F&amp;language=en_GB&amp;category=text&amp;title=Containing+ViewControllers&amp;description=For+a+project+that+I+am+currently+working+on+I+needed+to+implement+a+custom+container+view+controller.+I+was+feeling+my+way+forward+in+the+dark+for+the+most...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Podcast #32 &#8211; &#8220;WWDC Notably Absent&#8221;</title>
		<link>http://www.cocoanetics.com/2012/04/podcast-32-wwdc-notably-absent/</link>
		<comments>http://www.cocoanetics.com/2012/04/podcast-32-wwdc-notably-absent/#comments</comments>
		<pubDate>Sun, 08 Apr 2012 10:05:51 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6186</guid>
		<description><![CDATA[Episode 32, recorded April 8th 2012 Does Radar need to be fixed or not? Apple increases developer share for iAds. And we are on tenterhooks waiting for WWDC tickets to become available. &#160; iAd Developer Share Raised Apple raises revenue share going to developers from iAd to 70%, up from 60%. In a move that probably aimed at making iAd banners more attractive Apple raised the share to the same percentage developers are already getting for app sales and in-app purchases. The problem that people are still having with iAds is less the percentage they are getting, it&#8217;s the fill rate. Because of this they are mediation networks like the one from Google or a component like my DTBannerManger which combines iAds, AdMob and MobFox to get 100% fill rate with the highest paying ads prioritized higher. Nevertheless we appreciate the gesture, personally I feel it&#8217;s a bit more rounded that Apple gets 30% share in everything. Having a different percentage for a single service felt odd, not smooth, unlike Apple. At least they ironed this out for whatever reasons. Miscellaneous Announcements Apple has made new material available on the App Store Resource Center which you can use to promote your app with Apple&#8217;s blessing. On this page you can find the official &#8220;Available on the App Store&#8221; badge with instructions how you may and may not modify and use this. There are also official high resolution images for iOS devices which you can use in photo montages showing your app running on a device. The announcement mentioned new localized versions of the badge in Simplified and Traditional Chinese, Japanese, and Portuguese. There where several great links in this week&#8217;s installment of the iOS Dev Weekly newsletter. I got the WWDC ticket availability stats post from there as well as the next two items: There&#8217;s a cool guide on TheIconmaster.com that explains how to make a shortcut to new Photostream images in your Finder. This enables you to see new screenshots pop up right away on your Mac after you made them on your iOS devices. The advantage here is that you don&#8217;t have to have iPhoto running and iCloud sync working over peer-to-peer when your devices are on the same WiFi network. There is a smart search feature in Finder that automatically updates when new files appear. By combining this with a search for PNG files and the photo stream sync folder you&#8217;re set. There is an extensive code style guide on NearTheSpeedOfLight.com. It describes in great detail how you should style your code. From naming conventions to tips on how to structure your APIs. This joins the ZDS Code Style Guide by Marcus Zarra and the Google Objective-C Style Guide in trying to bring order to our chaotic code. While the contained details in all three guides might remind you a bit of Obsessive Compulsive Disorder (OCD) there are nevertheless many good reasons for why it makes sense to do certain things a certain way. If not following it slavishly it might do wonders on your own code style and code readability if you pick up a couple of pointers when skimming through these guides. App Review Weather Report: New Apps 97% chance of being approved in 5 days, Updates 99%. This week was somewhat uneventful, probably because I was on vacation. Could it be that Apple is aware that many developers are taking the week off leading up to the Easter holidays? I mean, if they would have announced the 2012 Worldwide Developer Conference in this week then they would have annoyed all those vacationing people. I for one was glad that they didn&#8217;t because it saved me from having to deal with somebody else buying a ticket for me while I am incommunicado. WWDC 2012, &#8230; NOT! Somebody &#8211; whose name I forgot &#8211; did a linear regression on previous announcement dates and ended up seeing April 18th as the most likely date that tickets could go on sale. Scott McAlister compiled a complete list of when tickets went on sale in relation to the conference dates for the last 8 years. Before the iPhone there were around 4 months lead time. For the past 4 years there were between 40 and 88 days lead time, that equates to around 2 months. If we take the speculative date of 11th of June then that means we are today just over 2 months way. By the way, the dates 11th through 15th of June are the only guess we have based on the Moscone West event calendar which has a &#8220;Corporate Meeting&#8221; by an unnamed company. Any day now&#8230;. Apple has no rush, its not that the event will not sell out in under 10 hours. To allow developers to be notified when tickets become available there is WWDCalerts.com which announced that they have 9000 [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/podcast-32-wwdc-notably-absent/"></g:plusone></div><p>Episode 32, recorded April 8th 2012</p>
<p>Does Radar need to be fixed or not? Apple increases developer share for iAds. And we are on tenterhooks waiting for WWDC tickets to become available.</p>

<p><span id="more-6186"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>iAd Developer Share Raised</h3>
<p>Apple raises revenue share going to developers from iAd to 70%, up from 60%. In a move that probably aimed at making iAd banners more attractive Apple raised the share to the same percentage developers are already getting for app sales and in-app purchases. The problem that people are still having with iAds is less the percentage they are getting, it&#8217;s the fill rate.</p>
<p>Because of this they are mediation networks like the one from Google or a component like my <a href="http://www.cocoanetics.com/parts/dtbannermanager/">DTBannerManger</a> which combines iAds, AdMob and MobFox to get 100% fill rate with the highest paying ads prioritized higher. Nevertheless we appreciate the gesture, personally I feel it&#8217;s a bit more rounded that Apple gets 30% share in everything.</p>
<p>Having a different percentage for a single service felt odd, not smooth, unlike Apple. At least they ironed this out for whatever reasons.</p>
<h3>Miscellaneous Announcements</h3>
<p>Apple has made new material available on the <a href="https://developer.apple.com/appstore/resources/marketing/index.html">App Store Resource Center</a> which you can use to promote your app with Apple&#8217;s blessing. On this page you can find the official &#8220;Available on the App Store&#8221; badge with instructions how you may and may not modify and use this. There are also official high resolution images for iOS devices which you can use in photo montages showing your app running on a device. The announcement mentioned new localized versions of the badge in Simplified and Traditional Chinese, Japanese, and Portuguese.</p>
<p>There where several great links in this week&#8217;s installment of the <a href="http://iosdevweekly.com/">iOS Dev Weekly newsletter</a>. I got the WWDC ticket availability stats post from there as well as the next two items:</p>
<p>There&#8217;s a cool guide on TheIconmaster.com that <a href="http://theiconmaster.com/2012/04/the-easy-way-to-get-ios-screenshots-on-your-mac">explains</a> how to make a shortcut to new Photostream images in your Finder. This enables you to see new screenshots pop up right away on your Mac after you made them on your iOS devices. The advantage here is that you don&#8217;t have to have iPhoto running and iCloud sync working over peer-to-peer when your devices are on the same WiFi network. There is a smart search feature in Finder that automatically updates when new files appear. By combining this with a search for PNG files and the photo stream sync folder you&#8217;re set.</p>
<p>There is an extensive code style guide on NearTheSpeedOfLight.com. It describes in <a href="http://nearthespeedoflight.com/style/guide">great detail</a> how you should style your code. From naming conventions to tips on how to structure your APIs. This joins the <a href="http://www.cimgf.com/zds-code-style-guide/">ZDS Code Style Guide</a> by Marcus Zarra and the <a href="http://google-styleguide.googlecode.com/svn/trunk/objcguide.xml">Google Objective-C Style Guide</a> in trying to bring order to our chaotic code. While the contained details in all three guides might remind you a bit of Obsessive Compulsive Disorder (OCD) there are nevertheless many good reasons for why it makes sense to do certain things a certain way. If not following it slavishly it might do wonders on your own code style and code readability if you pick up a couple of pointers when skimming through these guides.</p>
<p>App Review Weather Report: New Apps 97% chance of being approved in 5 days, Updates 99%.</p>
<p>This week was somewhat uneventful, probably because I was on vacation. Could it be that Apple is aware that many developers are taking the week off leading up to the Easter holidays? I mean, if they would have announced the 2012 Worldwide Developer Conference in this week then they would have annoyed all those vacationing people. I for one was glad that they didn&#8217;t because it saved me from having to deal with somebody else buying a ticket for me while I am incommunicado.</p>
<h3>WWDC 2012, &#8230; NOT!</h3>
<p>Somebody &#8211; whose name I forgot &#8211; did a linear regression on previous announcement dates and ended up seeing April 18th as the most likely date that tickets could go on sale. Scott McAlister <a href="http://4arrowsmedia.com/blog/2012/04/04/waiting-for-wwdc12-registration-to-open">compiled a complete list</a> of when tickets went on sale in relation to the conference dates for the last 8 years. Before the iPhone there were around 4 months lead time. For the past 4 years there were between 40 and 88 days lead time, that equates to around 2 months.</p>
<p>If we take the speculative date of 11th of June then that means we are today just over 2 months way. By the way, the dates 11th through 15th of June are the only guess we have based on the Moscone West event calendar which has a &#8220;Corporate Meeting&#8221; <a href="http://www.moscone.com/site/do/event/list;jsessionid=0AC51EA37064729238D3520237387F5A?nav.type=0&amp;nav.filter=1206&amp;nav.base=1204">by an unnamed company</a>. Any day now&#8230;.</p>
<p>Apple has no rush, its not that the event will not sell out in under 10 hours. To allow developers to be notified when tickets become available there is <a href="http://wwdcalerts.com/">WWDCalerts.com</a> which announced that they have 9000 subscribers so far. Mind you all these are competing for about 5000 tickets. Well that REALLY scares me.</p>
<p>I talked to <a href="http://twitter.com/jgeleynse">John Geylense</a> &#8211; head of developer evangelism at Apple &#8211; at last years Apple tech Tour in London. When I suggested to him that Apple should do one regional WWDC per continent he responded that he thought that this would be too expensive and that they couldn&#8217;t ship around all the engineers to the events. Then I pointed out that maybe 3 events &#8211; evenly distributed around the globe &#8211; would probably cost less than the 10 road show events combined because of all the flights and hotel rooms they would have had to book for the road show.</p>
<p>Though I fear that this suggestion &#8211; which probably many other developers have given as well &#8211; has fallen on deaf ears. If I were a betting man then I would still put my money on a single WWDC in June, followed by a 10 city road show later this year. Oh wait &#8230; I AM betting on this, because I already purchased a flight and hotel for 2 weeks in June. And apparently many others as well, because I found that the hotel room costs twice the normal rate during the rumored week of WWDC.</p>
<p>Either way Apple should announce the event at least 3 weeks beforehand simply for the reason that peoples who will fly to the USA for the event will have to register for <a href="https://esta.cbp.dhs.gov/esta/">Electronic System for Travel Authorization</a> if their country is part of the Visa Waiver system. If I am not mistaken you&#8217;ll have to do that at least 3 weeks before traveling.</p>
<p>Some creative developers have begun filing <a href="http://openradar.appspot.com/11176274">Radars</a> to express their frustration with not being able to buy a ticket or even knowing the official date. Unfortunately that seems to be the only way to communicate with Apple when we are dissatisfied with them. Just as unfortunately you cannot ever hope to get a useful response for these kinds of non-technical bug reports.</p>
<p>The other creative way I found how some people deal with the fear of missing out is to form Dub-Dub-Buddy-Teams. Thereby two developers both agree to buy an extra ticket for each other, just in case. This way there is a higher chance that both will get a ticket and if there are any left over it would be easy to find a buyer for that.</p>
<h3>Radar, To Fix or Not To Fix</h3>
<p>Speaking of Radar. The number of people who have registered their Radar-fixing Radar at <a href="http://fixradarorgtfo.com/">Fix Radar or GTFO</a> is holding at 329 which is a sad and low number. I would have thought that this cause should have been able to unite more than 300 developers. The goal of this initiative is to inspire Apple to improve their bug tracking and feature requesting system. I inquired why many more developers are taking objection to the goal of the initiative or the tone it is written in.</p>
<p>Some developers are afraid that they might anger somebody at Apple. And that this would cause Apple engineers to delay fixing the actual bugs they filed. While I can understand this fear, I refuse to believe that Apple engineers are vengeful and I refuse that this sort of egotistical thinking would be the norm.</p>
<p>Oleg Andreev even goes as far as <a href="http://blog.oleganza.com/post/18857769042/fix-radar-or-gtfo-is-nonsense">calling the initiative &#8220;nonsense</a>&#8220;. He wrote:</p>
<blockquote><p>Developers do not need a radar. Apple needs it. And they make it good enough for themselves, not for 3rd party developers. If the UI sucks and they get 10 times less bugs than people would love to file, it must be something they are okay with.</p></blockquote>
<p>I&#8217;m interested in your opinion. Did you file your duplicate Radar mentioning the one from the site? Or did you write a lengthy blog post explaining why this is futile? Or if you did neither, what is your reason for your inactivity? Could not be bothered? Leave me a voicemail under <strong>(415) 860-4324</strong>.</p>
<p>Peter Steinberger caught a glimpse of Apple&#8217;s internal Radar.app and tweeted:</p>
<blockquote><p>The funny thing is, now that I&#8217;ve seen Radar.app, I totally understand why Apple never gonna release that. ^^</p></blockquote>
<p>So it might be simple embarrassment why Apple does not let us have the Radar app so far.</p>
<p>I have my doubts that Apple will every open the issue tracking system even a tiny crack. So that&#8217;s why you should also post a copy of your bug report to the <a href="http://openradar.appspot.com/page/1">OpenRadar</a> site hosted on Google Apps. Every now and then when I trip on a bug I found &#8211; when googling for it &#8211; that either somebody asked about this bug on Stack Overflow or there is an Open Radar entry for it. If you then file your own Radar you can mention the other Radar for reference. That probably makes the Apple engineer&#8217;s live easier to categorize the bug report as well as gives us some peace of mind that we can be reasonably sure that it is not our code that has a fault.</p>
<h3>Xcode Jobs</h3>
<p>In the previous episode I told you about this new hobby project I started and called <a href="http://www.xcodejobs.com">XcodeJobs.com</a>. The idea here is basically that through all the Twittering that I do I see many iOS developers and development companies looking to hire iOS developers for fixed staff positions. Now it is my believe that regular job adverts just don&#8217;t cut it any more to capture the attention of experienced developers. You need to be a bit more creative than simply list all the skills you are looking for. Why should this iOS expert be interested in working for you when can just as well can have his own small business doing contract work?</p>
<p>XcodeJobs.com is set up such that if you sign in you immediately have the rights to create a blog post with a creative description of what you do and why candidates should closer look at your company. The best example I&#8217;ve ever seen for a <a title="iOS Jobs Rundown" href="http://www.cocoanetics.com/2011/05/ios-jobs-rundown/">creative iOS job</a> advert was by Polarbear Farms. They sort of a billboard that looked a bit like a blue print. This brilliantly examplifies how to create an advert that is both memorable and intriguing. The link to the one <a title="iOS Jobs Rundown" href="http://www.cocoanetics.com/2011/05/ios-jobs-rundown/">iOS Jobs rundown</a> I did a while back on my blog is also in the show notes.</p>
<p>The blog goes together with a Twitter account by the same name which I&#8217;m now using to retweet all the job offers that come before my eyes. Though I&#8217;m filtering a bit there as well, I have a bad feeling about retweeting job tweets that have a #jobs hash tag or that lead to websites that are obviously commercial recruiting agencies. That&#8217;s another thing that you definitely shouldn&#8217;t use if you are looking to prove your originality to your next iOS developer employee.</p>
<p>So &#8211; long story short &#8211; if you&#8217;re ever looking for somebody, then please do a creative ad at XcodeJobs.com or if you couldn&#8217;t be bothered then at least tweet a link to a job offer on your own company website so that I can retweet it.</p>
<h3>Feedback</h3>
<p>I love to hear from you, you can email me at oliver@cocoanetics.com or tweet me @cocoanetics. If you want to give me audio feedback or have some interesting comment for me to play on the show please call my Google Voice mailbox:  <strong>(415) 860-4324</strong></p>
<p>&nbsp;</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6186&amp;md5=72df275ea0e94c1c725c47bdbef7826a" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/podcast-32-wwdc-notably-absent/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.cocoanetics.com/files/Cocoanetics_032.mp3" length="21741244" type="audio/mpeg" />
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fpodcast-32-wwdc-notably-absent%2F&amp;language=en_GB&amp;category=text&amp;title=Podcast+%2332+%26%238211%3B+%26%238220%3BWWDC+Notably+Absent%26%238221%3B&amp;description=Episode+32%2C+recorded+April+8th+2012+Does+Radar+need+to+be+fixed+or+not%3F+Apple+increases+developer+share+for+iAds.+And+we+are+on+tenterhooks+waiting+for+WWDC+tickets+to...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Getting Double Financial Reports</title>
		<link>http://www.cocoanetics.com/2012/04/getting-double-financial-reports/</link>
		<comments>http://www.cocoanetics.com/2012/04/getting-double-financial-reports/#comments</comments>
		<pubDate>Fri, 06 Apr 2012 18:18:29 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6204</guid>
		<description><![CDATA[I reported late in 2011 on what the process is to move from an individual to a company developer account. One effect of this change is that you are getting a new developer account identifier which is a long number beginning with an 8. The main advantage of this move is that you can have multiple team members. Having been on a company account for a couple of months you might notice that you get daily, weekly and financial reports for both the old and the new account. On iTunes Connect you have a selection to choose the old and the new account. While you cease to receive entires on the daily and weekly reports after a very short transition period you will see financial reports to go on in parallel quite some time longer. I have been wondering why this is and through probing inquiry with Apple&#8217;s Finance Team I managed to uncover the reason for this. &#160; I switched in October 2011 and you can see a drastic drop in the financial report numbers after the switch. But I still have  a couple of dollars of earnings as late as the March sales report for USA. The explanation in one word: Sarbanes-Oxley, in one sentence: It&#8217;s the law! No Back-Dating Allowed When a customer purchases an app they make that purchase with a credit card, since they are unable to submit payment with cash through iTunes. Once they click to buy your app, that sale will appear in the daily trend reports. The credit card company has to release these funds to Apple, which may be on the same day, within a week, or even longer. Therefore, there are times that a customer clicks to purchase an app in one fiscal month, but the funds are released to Apple in a different fiscal month. When the credit card company releases the funds to Apple, they get reported in the financial reports. They are only allowed to report transactions that have completed their financial systems, and that may not necessarily be the month in which the transaction was initiated. Apple has to report those funds when they are received and cannot back date them as that would be illegal accounting acceding to Sarbanes-Oxley rules. This is why you may see differences in the trends reports as opposed to the financial reports. Apple has no control over how long it takes the credit card companies to release the sales earnings to them. Conclusion In summary it is not Apple&#8217;s fault but entirely the credit card companies&#8217; which apparently can take several months (!) to release funds for individual purchases. I was told that this transitional period can last several months and while it is a pain to deal with those minute extra reports I can only hope that some day the credit card companies have found and reported all these individual purchases to Apple. Oh well, maybe &#8230; some day &#8230;]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/getting-double-financial-reports/"></g:plusone></div><p>I reported late in 2011 on what the process is to <a title="Moving from Individual to Company" href="http://www.cocoanetics.com/2011/10/moving-from-individual-to-company/">move from an individual to a company developer account</a>. One effect of this change is that you are getting a new developer account identifier which is a long number beginning with an 8. The main advantage of this move is that you can have multiple team members.</p>
<p>Having been on a company account for a couple of months you might notice that you get daily, weekly and financial reports for both the old and the new account. On iTunes Connect you have a selection to choose the old and the new account. While you cease to receive entires on the daily and weekly reports after a very short transition period you will see financial reports to go on in parallel quite some time longer.</p>
<p>I have been wondering why this is and through probing inquiry with Apple&#8217;s Finance Team I managed to uncover the reason for this.</p>
<p><span id="more-6204"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>I switched in October 2011 and you can see a drastic drop in the financial report numbers after the switch. But I still have  a couple of dollars of earnings as late as the March sales report for USA. The explanation in one word: <a href="http://en.wikipedia.org/wiki/Sarbanes–Oxley_Act">Sarbanes-Oxley</a>, in one sentence: <em>It&#8217;s the law!</em></p>
<h3>No Back-Dating Allowed</h3>
<p>When a customer purchases an app they make that purchase with a<strong> credit card</strong>, since they are unable to submit payment with cash through iTunes. Once they click to buy your app, that sale will appear in the <strong>daily trend reports</strong>. The credit card company has to release these funds to Apple, which may be on the same day, within a week, or even longer.</p>
<p>Therefore, there are times that a customer clicks to purchase an app in one fiscal month, but the <strong>funds are released</strong> to Apple in a different fiscal month. When the credit card company releases the funds to Apple, they get reported in the <strong>financial reports</strong>. They are only allowed to report transactions that have completed their financial systems, and that may not necessarily be the month in which the transaction was initiated.</p>
<p>Apple has to report those funds when they are received and <strong>cannot back date</strong> them as that would be illegal accounting acceding to Sarbanes-Oxley rules. This is why you may see differences in the trends reports as opposed to the financial reports. Apple has no control over how long it takes the credit card companies to release the sales earnings to them.</p>
<h3>Conclusion</h3>
<p>In summary it is not Apple&#8217;s fault but entirely the credit card companies&#8217; which apparently can take several months (!) to release funds for individual purchases.</p>
<p>I was told that this transitional period can last several months and while it is a pain to deal with those minute extra reports I can only hope that some day the credit card companies have found and reported all these individual purchases to Apple.</p>
<p>Oh well, maybe &#8230; some day &#8230;</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6204&amp;md5=3fb71de0307ca07abc2969cafa6f3424" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/getting-double-financial-reports/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fgetting-double-financial-reports%2F&amp;language=en_GB&amp;category=text&amp;title=Getting+Double+Financial+Reports&amp;description=I+reported+late+in+2011+on+what+the+process+is+to+move+from+an+individual+to+a+company+developer+account.+One+effect+of+this+change+is+that+you+are+getting...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>DTMorseKeyboard Tutorial</title>
		<link>http://www.cocoanetics.com/2012/04/dtmorsekeyboard-tutorial/</link>
		<comments>http://www.cocoanetics.com/2012/04/dtmorsekeyboard-tutorial/#comments</comments>
		<pubDate>Sun, 01 Apr 2012 21:55:43 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6188</guid>
		<description><![CDATA[Inspired by the Gmail Tap April Fools joke by Google I felt inspired to program the same thing for iOS. There we have custom input views as well as the UIKeyInput protocol and so I figured it should be an easy undertaking. The whole affair took slightly more than one hour and I was hoping to record it in 1 second intervals with ScreenNinja. Unfortunately it seems that this otherwise fabulous app crapped out on me. I later discovered that the MOV file had actually finished before the crash, so to my delight (and hopefully yours too) you can follow this tutorial on YouTube. &#160; In the video you see the whole process from start to finish. Let me just offer some clarifications in this post so that you better understand what I am doing. http://www.youtube.com/watch?v=w5lRUE1Xet8 In iOS Apple provides us with two protocols, UIKeyInput for inputting single key strokes and UITextInput for everything that&#8217;s more than single keys, like text selection, auto correction etc. As part of UITextInput each conforming UIView implements an inputView property that can be any UIView. If set this inputView is shown instead of the standard keyboard, if not then you see the keyboard. So for our example all we need is a UIView with one button for the Morse button. The Gmail Tap prank interface uses two buttons, one for a dot, one for a dash. When researching Morse Code on Wikipedia I found one slight problem with this approach. Individual letters have to have a slight pause from each other because otherwise we wouldn&#8217;t know if by a dot the user intends to write an E or one of the other dozen or so combinations that have a dot as the first part of a sequence. The Morse alphabet doesn&#8217;t just consist of 2 letters, but rather it uses 3 which are &#8220;dit&#8221;, &#8220;dah&#8221; and a silent pause. Given that &#8220;dit&#8221; is the shortest element, a &#8220;dah&#8221; is three times as long. Sequence elements are spaced one &#8220;dit&#8221; apart, Letters are spaced one &#8220;dah&#8221; apart and the length of 7 &#8220;dits&#8221; signifies a word break. Really, I am not making this up! First step is to override canBecomeFirstResponder and return YES. For simplicy I just wired up the UIControlEventTouchUpInside and the UIControlEventTouchDown to two methods and I&#8217;m using the time interval between the touch down and the touch up to determine if we saw a &#8220;dit&#8221; or &#8220;dah&#8221;. A bit of pause handling with performSelector:withObject:afterDelay: was necessary to get the breaks decoded. Then there is a lookup table from which to draw the actual letters once a letter break is encountered. + &#40;void&#41;initialize &#123; morseLookup = &#91;NSDictionary dictionaryWithObjectsAndKeys:@&#34;a&#34;, @&#34;··−·&#34;, @&#34;b&#34;,@&#34;−···&#34;, @&#34;c&#34;,@&#34;−·−·&#34;, @&#34;d&#34;,@&#34;−··&#34;, @&#34;e&#34;,@&#34;·&#34;, @&#34;f&#34;,@&#34;··−·&#34;, @&#34;g&#34;,@&#34;−−·&#34;, @&#34;i&#34;,@&#34;··&#34;, @&#34;j&#34;,@&#34;·−−−&#34;, @&#34;k&#34;,@&#34;−·−&#34;, @&#34;l&#34;,@&#34;·−··&#34;, @&#34;m&#34;,@&#34;−−&#34;, @&#34;n&#34;,@&#34;−·&#34;, @&#34;o&#34;,@&#34;−−−&#34;, @&#34;p&#34;,@&#34;·−−·&#34;, @&#34;q&#34;,@&#34;−−·−&#34;, @&#34;r&#34;,@&#34;·−·&#34;, @&#34;s&#34;,@&#34;···&#34;, @&#34;t&#34;,@&#34;−&#34;, @&#34;u&#34;,@&#34;··−&#34;, @&#34;v&#34;,@&#34;···−&#34;, @&#34;w&#34;,@&#34;·−−&#34;, @&#34;x&#34;,@&#34;−··−&#34;, @&#34;y&#34;,@&#34;−·−−&#34;, @&#34;z&#34;,@&#34;−−··&#34;, @&#34;0&#34;,@&#34;−−−−−&#34;, @&#34;1&#34;,@&#34;·−−−−&#34;, @&#34;2&#34;,@&#34;··−−−&#34;, @&#34;3&#34;,@&#34;···−−&#34;, @&#34;4&#34;,@&#34;····−&#34;, @&#34;5&#34;,@&#34;·····&#34;, @&#34;6&#34;,@&#34;−····&#34;, @&#34;7&#34;,@&#34;−−···&#34;, @&#34;8&#34;,@&#34;−−−··&#34;, @&#34;9&#34;,@&#34;−−−−·&#34;, nil&#93;; &#160; for &#40;NSString *oneSequence in &#91;morseLookup allKeys&#93;&#41; &#123; _longestMorseSequence = MAX&#40;_longestMorseSequence, &#91;oneSequence length&#93;&#41;; &#125; &#125; The final piece of the puzzle is that we somehow need to have a pointer to the text control so that we can insert the detected characters. I was puzzled by the fact there does not seem to be an obvious method to do that. So I went for the obvious method of setting it in the init. The input delegate (e.g. a UITextField) has to be compliant with the UIKeyInput protocol and therefore we know that it must have an insertText: method. This will insert the passed string at the current cursor position. Conclusion Turns out the by far hardest part of making our own custom keyboard is the input logic, which itself becomes way more complicated by having to invent algorithms to decode Morse sequences. There are several improvements that spring to mind right away. Auto-Completion would be one where it could show a decreasing number of possible sequences based on the sequence for a single letter so far. Maybe that could be shown if the finger is lifted outside of the button. Another question to tackle is how to actually delete text, the backspace key if you will. Maybe by doing a &#8220;dit&#8221; that begins on the button, but ends outside to the left of it? Finally there should be no set amount of time for a &#8220;dit&#8221;, experienced Morse-o-graphers can have much shorter dits as long as the relation of dits, dats and pauses remains mostly constant. In this tutorial I went for the easiest method of simply using the latest dit&#8217;s duration, but it would be nice to average this over time. Source code of the full project is available on GitHub.]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/dtmorsekeyboard-tutorial/"></g:plusone></div><p>Inspired by the <a href="http://mail.google.com/mail/help/promos/tap/index.html">Gmail Tap</a> April Fools joke by Google I felt inspired to program the same thing for iOS. There we have custom input views as well as the UIKeyInput protocol and so I figured it should be an easy undertaking.</p>
<p>The whole affair took slightly more than one hour and I was hoping to record it in 1 second intervals with ScreenNinja. Unfortunately it seems that this otherwise fabulous app crapped out on me. I later discovered that the MOV file had actually finished before the crash, so to my delight (and hopefully yours too) you can follow this tutorial on YouTube.</p>
<p><span id="more-6188"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>In the video you see the whole process from start to finish. Let me just offer some clarifications in this post so that you better understand what I am doing.</p>
<p><a href="http://www.youtube.com/watch?v=w5lRUE1Xet8&#038;fmt=18">http://www.youtube.com/watch?v=w5lRUE1Xet8</a></p>
<p>In iOS Apple provides us with two protocols, UIKeyInput for inputting single key strokes and UITextInput for everything that&#8217;s more than single keys, like text selection, auto correction etc. As part of UITextInput each conforming UIView implements an inputView property that can be any UIView.</p>
<p>If set this inputView is shown instead of the standard keyboard, if not then you see the keyboard. So for our example all we need is a UIView with one button for the Morse button.</p>
<p><a href="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-01-um-22.44.07.png"><img class="alignnone size-full wp-image-6190" title="Morse Button UI" src="http://www.cocoanetics.com/files/Bildschirmfoto-2012-04-01-um-22.44.07.png" alt="" width="396" height="744" /></a></p>
<p>The Gmail Tap prank interface uses two buttons, one for a dot, one for a dash. When researching <a href="http://en.wikipedia.org/wiki/Morse_code">Morse Code</a> on Wikipedia I found one slight problem with this approach. Individual letters have to have a slight pause from each other because otherwise we wouldn&#8217;t know if by a dot the user intends to write an E or one of the other dozen or so combinations that have a dot as the first part of a sequence.</p>
<p>The Morse alphabet doesn&#8217;t just consist of 2 letters, but rather it uses 3 which are &#8220;dit&#8221;, &#8220;dah&#8221; and a silent pause. Given that &#8220;dit&#8221; is the shortest element, a &#8220;dah&#8221; is three times as long. Sequence elements are spaced one &#8220;dit&#8221; apart, Letters are spaced one &#8220;dah&#8221; apart and the length of 7 &#8220;dits&#8221; signifies a word break. Really, I am not making this up!</p>
<p>First step is to override canBecomeFirstResponder and return YES.</p>
<p>For simplicy I just wired up the UIControlEventTouchUpInside and the UIControlEventTouchDown to two methods and I&#8217;m using the time interval between the touch down and the touch up to determine if we saw a &#8220;dit&#8221; or &#8220;dah&#8221;. A bit of pause handling with performSelector:withObject:afterDelay: was necessary to get the breaks decoded.</p>
<p>Then there is a lookup table from which to draw the actual letters once a letter break is encountered.</p>

<div class="wp_codebox"><table><tr id="p6188113"><td class="code" id="p6188code113"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>initialize
<span style="color: #002200;">&#123;</span>
	morseLookup <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;a&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;··−·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;b&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−···&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;c&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−·−·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;d&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−··&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;e&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;f&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;··−·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;g&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;i&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;··&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;j&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·−−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;k&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−·−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;l&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·−··&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;m&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;n&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;o&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;p&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·−−·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;q&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−·−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;r&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·−·&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;s&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;···&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;t&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;u&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;··−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;v&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;···−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;w&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;x&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−··−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;y&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−·−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;z&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−··&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;0&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−−−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;1&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·−−−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;2&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;··−−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;3&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;···−−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;4&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;····−&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;5&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;·····&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;6&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−····&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;7&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−···&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;8&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−−··&quot;</span>,
						<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;9&quot;</span>,<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;−−−−·&quot;</span>,
						<span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>oneSequence <span style="color: #a61390;">in</span> <span style="color: #002200;">&#91;</span>morseLookup allKeys<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		_longestMorseSequence <span style="color: #002200;">=</span> MAX<span style="color: #002200;">&#40;</span>_longestMorseSequence, <span style="color: #002200;">&#91;</span>oneSequence length<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>The final piece of the puzzle is that we somehow need to have a pointer to the text control so that we can insert the detected characters. I was puzzled by the fact there does not seem to be an obvious method to do that. So I went for the obvious method of setting it in the init.</p>
<p>The input delegate (e.g. a UITextField) has to be compliant with the UIKeyInput protocol and therefore we know that it must have an insertText: method. This will insert the passed string at the current cursor position.</p>
<h3>Conclusion</h3>
<p>Turns out the by far hardest part of making our own custom keyboard is the input logic, which itself becomes way more complicated by having to invent algorithms to decode Morse sequences. </p>
<p>There are several improvements that spring to mind right away. Auto-Completion would be one where it could show a decreasing number of possible sequences based on the sequence for a single letter so far. Maybe that could be shown if the finger is lifted outside of the button.</p>
<p>Another question to tackle is how to actually delete text, the backspace key if you will. Maybe by doing a &#8220;dit&#8221; that begins on the button, but ends outside to the left of it?</p>
<p>Finally there should be no set amount of time for a &#8220;dit&#8221;, experienced Morse-o-graphers can have much shorter dits as long as the relation of dits, dats and pauses remains mostly constant. In this tutorial I went for the easiest method of simply using the latest dit&#8217;s duration, but it would be nice to average this over time.</p>
<p>Source code of the full project is <a href="https://github.com/Cocoanetics/DTMorseKeyboard">available on GitHub</a>.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6188&amp;md5=5f53a0e9042a02307fabf95d8e69b5be" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/dtmorsekeyboard-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fdtmorsekeyboard-tutorial%2F&amp;language=en_GB&amp;category=text&amp;title=DTMorseKeyboard+Tutorial&amp;description=Inspired+by+the+Gmail+Tap+April+Fools+joke+by+Google+I+felt+inspired+to+program+the+same+thing+for+iOS.+There+we+have+custom+input+views+as+well+as+the...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>OMG! SocialGate!</title>
		<link>http://www.cocoanetics.com/2012/04/omg-socialgate/</link>
		<comments>http://www.cocoanetics.com/2012/04/omg-socialgate/#comments</comments>
		<pubDate>Sun, 01 Apr 2012 09:06:45 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6179</guid>
		<description><![CDATA[I was already packing my suitcase for my vacation next week when I learned about the makings of the biggest scandal that is about to happen on the Apple campus. And I am not talking about AntennaGate or WarmGate, this is a REAL scandal! I just had to sit down and document the facts &#8211; as we know them so far. A source close to the matter informed me (on condition of anonymity) that Apple CEO Tim Cook has set a plan in motion that will &#8211; so he fears &#8211; dramatically tarnish Apple&#8217;s reputation and throw them back to the technological stone age &#8230; at least when it comes to social media. &#160; It is a little know fact that shortly after returning to save Apple in the late 1980s Apple founder Steve Jobs established a strict ban on smoking cigarettes on the Apple campus. This was not even known to his biographer and thus omitted from the book. Contrary to what was written in the biography it were not health concerns or even a public mandate, but Jobs had gotten hold of an internal chart that showed a correlation of number of source code lines dropping and the level of smoke addiction of individual employees. Smokers&#8217; productivity was roughly 5% lower than their peers, and Jobs reasoned that the frequent smoking breaks must have been the reason for that. Steve Jobs was well aware that this was a very unpopular move and so he mandated that this be kept a secret. This ban took place in 1998 one year after US President Bill Clinton signed Executive Order 13058 which banned &#8220;smoking in all interior spaces owned, rented, or leased by the Executive Branch of the Federal Government, as well as in any outdoor areas under executive branch control near air intake ducts. The rest is history, Apple was saved partially because of the invigorated productivity and rose again to become the most valuable brand in history. Apple&#8217;s current CEO Tim Cook had not been aware of this unpopular decision because he joined Apple much later, in 1998. They say &#8220;those who do not know past mistakes are bound to repeat them.&#8221;. This post is a chronicle of one CEO probably proving this adage right. Cook had already been acting as interim CEO when we learned in Spring 2011 that there had been a drastic decrease in programmer productivity as of late. This had resulted in iCloud being buggy and would not make the deadline of getting released at WWDC 2011 together with iOS 5 and the new iPhone. iCloud is Apple&#8217;s big bet and not being able to ship the iPhone 4S with iCloud in Summer  2011 caused the CEO to go on a rampage. No real solution was found and so Cook decided to preview iCloud to developers in June and do the actual launch of iPhone and iCloud in Fall. About the same time as this happened Apple &#8211; quite uncharacteristically &#8211; had begun talks to enter a partnership with Twitter to integrate their popular social network with Apple products. We know that the partnership was fruitful, Twitter gained even more popularity because of the tight integration with iOS and Apple finally was able to shed the ridicule they incurred from launching Ping. One side-deal of this partnership was that Apple would get access to the Twitter &#8220;firehose&#8221;, the unfiltered unrestricted live-stream of all tweets. This stream of tweets would be used to train the artificial intelligence product Siri which Apple had acquired in April 2010. But that was not the only use the CEO Cook had in mind for the combination of Siri and Twitter. Being &#8220;old school&#8221; and an avid runner Cook is considering social networking as much as a waste of time (and health) as smoking. He developed the theory that all these frequent interruption and &#8220;quick tweets&#8221; would be detrimental to programmer&#8217;s productivity. But before the partnership with Twitter and the acquisition of Siri he had lacked a way to prove this theory. Apple employees are living in constant fear of overstepping the line when it comes to social networking. My source told me that one of the first things that new hires are being told is that they should refrain from tweeting about work and keep their employment a secret from the public. This is why you often see profile descriptions like &#8220;I work for a fruit company&#8221; and &#8220;I speak for myself and not my employer&#8221; in Twitter profiles of Apple employees. Other ways of masquerading include discussing BMW cars, music and the liberal arts. Ironically these terms are forming a recognizable pattern that an AI like Siri can look for and this identify the Apple employees who are spending way too much time in &#8220;tweeting around&#8221; during working hours.  This finally [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/04/omg-socialgate/"></g:plusone></div><p>I was already packing my suitcase for my vacation next week when I learned about the makings of the biggest scandal that is about to happen on the Apple campus. And I am not talking about AntennaGate or WarmGate, this is a REAL scandal! I just had to sit down and document the facts &#8211; as we know them so far.</p>
<p>A source close to the matter informed me (on condition of anonymity) that Apple CEO Tim Cook has set a plan in motion that will &#8211; so he fears &#8211; dramatically tarnish Apple&#8217;s reputation and throw them back to the technological stone age &#8230; at least when it comes to social media.</p>
<p><span id="more-6179"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<p>It is a little know fact that shortly after returning to save Apple in the late 1980s Apple founder Steve Jobs established a strict ban on smoking cigarettes on the Apple campus. This was not even known to his biographer and thus omitted from the book. Contrary to what was written in the biography it were not health concerns or even a public mandate, but Jobs had gotten hold of an internal chart that showed a correlation of number of source code lines dropping and the level of smoke addiction of individual employees. Smokers&#8217; productivity was roughly 5% lower than their peers, and Jobs reasoned that the frequent smoking breaks must have been the reason for that.</p>
<p>Steve Jobs was well aware that this was a very unpopular move and so he mandated that this be kept a secret. This ban took place <a href="http://en.wikipedia.org/wiki/Steve_Jobs">in 1998</a> one year after US President Bill Clinton signed <a href="http://en.wikisource.org/wiki/Executive_Order_13058">Executive Order 13058</a> which banned &#8220;smoking in all interior spaces owned, rented, or leased by the Executive Branch of the Federal Government, as well as in any outdoor areas under executive branch control near air intake ducts. The rest is history, Apple was saved partially because of the invigorated productivity and rose again to become the most valuable brand in history.</p>
<p>Apple&#8217;s current CEO Tim Cook had not been aware of this unpopular decision because he joined Apple much later, in <a href="http://en.wikipedia.org/wiki/Tim_Cook">1998</a>. They say <em>&#8220;those who do not know past mistakes are bound to repeat them.&#8221;. </em>This post is a chronicle of one CEO probably proving this adage right.</p>
<p>Cook had already been acting as interim CEO when we learned in Spring 2011 that there had been a drastic decrease in programmer productivity as of late. This had resulted in iCloud being buggy and would not make the deadline of getting released at WWDC 2011 together with iOS 5 and the new iPhone. iCloud is Apple&#8217;s big bet and not being able to ship the iPhone 4S with iCloud in Summer  2011 caused the CEO to go on a rampage. No real solution was found and so Cook decided to preview iCloud to developers in June and do the actual launch of iPhone and iCloud in Fall.</p>
<p>About the same time as this happened Apple &#8211; quite uncharacteristically &#8211; had begun talks to enter a partnership with Twitter to integrate their popular social network with Apple products. We know that the partnership was fruitful, Twitter gained even more popularity because of the tight integration with iOS and Apple finally was able to shed the ridicule they incurred from launching Ping. One side-deal of this partnership was that Apple would get access to the Twitter &#8220;firehose&#8221;, the unfiltered unrestricted live-stream of all tweets.</p>
<p>This stream of tweets would be used to train the artificial intelligence product Siri which Apple had acquired in April 2010. But that was not the only use the CEO Cook had in mind for the combination of Siri and Twitter.</p>
<p>Being &#8220;old school&#8221; and an avid runner Cook is considering social networking as much as a waste of time (and health) as smoking. He developed the theory that all these frequent interruption and &#8220;quick tweets&#8221; would be detrimental to programmer&#8217;s productivity. But before the partnership with Twitter and the acquisition of Siri he had lacked a way to prove this theory.</p>
<p>Apple employees are living in constant fear of overstepping the line when it comes to social networking. My source told me that one of the first things that new hires are being told is that they should refrain from tweeting about work and keep their employment a secret from the public. This is why you often see profile descriptions like <em>&#8220;I work for a fruit company&#8221;</em> and <em>&#8220;I speak for myself and not my employer&#8221;</em> in Twitter profiles of Apple employees. Other ways of masquerading include discussing BMW cars, music and the liberal arts.</p>
<p>Ironically these terms are forming a recognizable pattern that an AI like Siri can look for and this identify the Apple employees who are spending way too much time in &#8220;tweeting around&#8221; during working hours.  This finally gave Cook the information he needed to produce a list of 1000 most-distracted individuals who will find themselves on the ejection seat as of coming Monday.</p>
<p>On a recent conference call with investors call Cook had mentioned that <em>&#8220;we&#8217;re doing some things are differently now&#8221;</em> and we now know what he meant. Cook is known to be ruling with an iron fist over the &#8220;regular foot soldiers&#8221;. So in stark contrast to Steve Jobs, who was content with a ban, he is going to be laying off the individuals on his hot list.</p>
<p>Why now? Well Apple&#8217;s stock price is on an all time high and the next big event will be WWDC 2012 in June. So the strategy is to do the layoffs in April because the &#8220;shareholder value&#8221; can digest this the easiest right at this time.</p>
<p>Apple has been hiring new employees like crazy in the past few weeks, partly because the company is growing in leaps and bounds, partly because Cook has instructed his VPs to buffer the coming bloodletting. Also managers were instructed to not hire people who are overzealous on Twitter, Facebook and Google+. Instead an internal memo is instructing them to respond with <em>&#8220;sorry, but you weren&#8217;t a good fit&#8221;</em> when asked for the reason of rejections.</p>
<p>My own reaction to this &#8211; despite my disbelief &#8211; is that I couldn&#8217;t believe it to be true. In my humble opinion this will cause a major outcry in the developer community and Apple will find it much harder in the future to find good programmer talent. Of course Apple will deny it and try to silence laid off individuals by threatening severe legal actions. And if you know Apple&#8217;s Legal Department then you are afraid of them.</p>
<p>It is because of this that I am asking you to tell everyone about this shady maneuver. We should not let Tim Cook get away with dismantling our beloved Apple this way. <strong>Social networking is not a crime</strong> and even less it can be likened to smoking. We should let Apple know that if they seriously will go ahead with the layoffs then we&#8217;ll all be switching to developing for Android. I know I will.</p>
<p><em>Update: April Fools!!! Sorry if I caused any actual Apple Employee&#8217;s to sweat and hastily delete their Twitter accounts.</em></p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6179&amp;md5=2e74ab88d7be215fb0616c14fef962ee" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/04/omg-socialgate/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F04%2Fomg-socialgate%2F&amp;language=en_GB&amp;category=text&amp;title=OMG%21+SocialGate%21&amp;description=I+was+already+packing+my+suitcase+for+my+vacation+next+week+when+I+learned+about+the+makings+of+the+biggest+scandal+that+is+about+to+happen+on+the+Apple+campus....&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Podcast #31 &#8211; &#8220;UDID Fire&#8221;</title>
		<link>http://www.cocoanetics.com/2012/03/podcast-31-udid-fire/</link>
		<comments>http://www.cocoanetics.com/2012/03/podcast-31-udid-fire/#comments</comments>
		<pubDate>Sat, 31 Mar 2012 17:47:53 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6146</guid>
		<description><![CDATA[Episode 31, recorded Saturday March 31st, 2012 &#8211; UDID FIre Mach ado about UDID, jobs for iOS developers abound and my guest today is Appsfire Co-Founder Ouriel Ohayon. &#160; News Apple informed developers via e-mail that iTunes Connect will have individual reports for Sweden and Denmark from now on. For March, app sales earnings in Sweden and Denmark will be split and reported in two different documents, one covering the time period before the change and one covering the time period after the change. Earnings from sales that occurred before the change will be in the Euro-Zone (EUR) financial report. Earnings from after the change will be in the new financial reports for Sweden (SEK) and Denmark (DKK). I am wondering what the benefit to us developers will be. Are the reporting guys SEARCHING for work to do that nobody actually cares about, just so that they are not bored? Speaking of non-sensical changes: Apple invented two new price tiers. Tier 63 is $124.99 and Tier 69 is $174.99. Both tiers are available for both apps and In-App Purchases. Can anybody explain to my what this is good for? Are apps too cheap? Does Zynga want to sell more expensive In-App-Crap? You know, lower levels of tiers usually correspond with the price in dollars. The geek in me revolts, what is the secret algorithm here? UDID, or didn&#8217;t you? Now that some rumors seemed to indicate that Apple might be beginning to reject apps that are using the unique device identifier developers are scrambling and are ripping out the trusty old identification code and replacing it with something new. But that only seems to be part of the story. Tapbots published the original rejection letter they received from Apple and this contains some very interesting information. This letter says that they where sending identity information to their server without having asked the user. Apple seems to actually do a man-in-the-middle attack on HTTPS when reviewing our apps. Tapbots was sending the UDID in a HTTP GET request over HTTPS. If you simply look at the data packets then you don&#8217;t know the URL that is being requested because the first step in the HTTPS is to do a CONNECT. Then the GET is performed and already encrypted. This man-in-the-middle means that Apple has a tracing server that spoofs the HTTPS target and re-signs the packet such that it is still accepted by the URL connection on the device. This is technically easy, I blogged about how to spy on any app&#8217;s traffic with the Charles debugging proxy app. What&#8217;s interesting that we learn for the first time that not even encryption is holy to Apple. So if you are sending something naughty to your server, then don&#8217;t rely on HTTPS thinking that nobody can see the contents. Better to send hashes instead of plain text. This is sort of similar to when the Path app sent your address book. Many people ask: what should be use instead of UDID and the privacy advocates generally say: nothing. A user is not the same as a device. About the only market that requires to uniquely identify devices is advertising, especially when it comes to conversion tracking. If you need to have some sort of temporary identifier then you can use CFUUID to create one and then you can store it in the keychain. This will persist even when the app is removed as opposed to the user defaults. For those who are developing libraries for ad networks the de facto standard has become the OpenUDID project which is available on GitHub. It was developed by on of the founders of Appsfire. There is a second competing project called SecureUDID but when I surveyed the market as to which is winning I found that most ad networks had switched to using OpenUDID. This includes the MobFox framework which you might know that I originally developed. Flurry Analytics reports the relation of income of the three major app stores: Apple&#8217;s app store, the Amazon app store and Google Play (aka the Android app store). The comparison they came up with is this: $1 on Apple&#8217;s App Store is 89¢ on Kindle and 23¢ on Android What&#8217;s interesting is that Amazon is able to get the value proposition for developers into the vicinity of where it is for us iOS developers. Well it certainly helps to have the marketing experience of the world&#8217;s largest retailer and a dedicated device that locks people into their marketplace. And it still gives us a warm and fuzzy feeling that we are focussing on the app store where the most money is made. Our grass is greenest, yeah! Here&#8217;s another good reason why we developers should always buy the latest Apple devices. An iOS forensics company has created a tool [...]]]></description>
			<content:encoded><![CDATA[<div class="plus-one-wrap"><g:plusone href="http://www.cocoanetics.com/2012/03/podcast-31-udid-fire/"></g:plusone></div><p>Episode 31, recorded Saturday March 31st, 2012 &#8211; UDID FIre</p>
<p>Mach ado about UDID, jobs for iOS developers abound and my guest today is Appsfire Co-Founder Ouriel Ohayon.</p>

<p><span id="more-6146"></span></p>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
<div id="text-21" class="widget widget_text">
<div class="textwidget">
<p>&nbsp;</p>
</div></div>
</div>
<h3>News</h3>
<p>Apple informed developers via e-mail that iTunes Connect will have<strong> individual reports for Sweden and Denmark</strong> from now on. For March, app sales earnings in Sweden and Denmark will be split and reported in two different documents, one covering the time period before the change and one covering the time period after the change. Earnings from sales that occurred before the change will be in the Euro-Zone (EUR) financial report. Earnings from after the change will be in the new financial reports for Sweden (SEK) and Denmark (DKK).</p>
<p>I am wondering what the benefit to us developers will be. Are the reporting guys SEARCHING for work to do that nobody actually cares about, just so that they are not bored?</p>
<p>Speaking of non-sensical changes: Apple invented <strong>two new price tiers</strong>. Tier 63 is $124.99 and Tier 69 is $174.99. Both tiers are available for both apps and In-App Purchases. Can anybody explain to my what this is good for? Are apps too cheap? Does Zynga want to sell more expensive In-App-Crap? You know, lower levels of tiers usually correspond with the price in dollars. The geek in me revolts, what is the secret algorithm here?</p>
<p>UDID, or didn&#8217;t you? Now that some rumors seemed to indicate that Apple might be beginning to reject apps that are using the unique device identifier developers are scrambling and are ripping out the trusty old identification code and replacing it with something new. But that only seems to be <a title="UDID … or Didn’t U?" href="http://www.cocoanetics.com/2012/03/udid-or-didnt-u/">part of the story</a>. Tapbots published the original rejection letter they received from Apple and this contains some very interesting information. This letter says that they where sending identity information to their server without having asked the user.</p>
<p>Apple seems to actually do a man-in-the-middle attack on HTTPS when reviewing our apps. Tapbots was sending the UDID in a HTTP GET request over HTTPS. If you simply look at the data packets then you don&#8217;t know the URL that is being requested because the first step in the HTTPS is to do a CONNECT. Then the GET is performed and already encrypted. This man-in-the-middle means that Apple has a tracing server that spoofs the HTTPS target and re-signs the packet such that it is still accepted by the URL connection on the device.</p>
<p>This is technically easy, I blogged about how to <a title="How to Spy on the Web Traffic of any App" href="http://www.cocoanetics.com/2010/12/how-to-spy-on-the-web-traffic-of-any-app/">spy on any app&#8217;s traffic</a> with the Charles debugging proxy app. What&#8217;s interesting that we learn for the first time that not even encryption is holy to Apple. So if you are sending something naughty to your server, then don&#8217;t rely on HTTPS thinking that nobody can see the contents. Better to send hashes instead of plain text. This is sort of similar to when the Path app sent your address book.</p>
<p>Many people ask: what should be use instead of UDID and the privacy advocates generally say: nothing. A user is not the same as a device. About the only market that requires to uniquely identify devices is advertising, especially when it comes to conversion tracking. If you need to have some sort of temporary identifier then you can use CFUUID to create one and then you can store it in the keychain. This will persist even when the app is removed as opposed to the user defaults.</p>
<p>For those who are developing libraries for ad networks the de facto standard has become the <a href="https://github.com/ylechelle/OpenUDID">OpenUDID project</a> which is available on GitHub. It was developed by on of the founders of Appsfire. There is a second competing project called <a href="http://www.secureudid.org/">SecureUDID</a> but when I surveyed the market as to which is winning I found that most ad networks had switched to using OpenUDID. This includes the <a title="MobFox" href="http://www.cocoanetics.com/2010/10/mobfox/">MobFox framework</a> which you might know that I originally developed.</p>
<p>Flurry Analytics <a href="http://tech.fortune.cnn.com/2012/03/30/1-on-apples-app-store-is-89-on-kindle-and-23-on-android/">reports</a> the relation of income of the three major app stores: Apple&#8217;s app store, the Amazon app store and Google Play (aka the Android app store). The comparison they came up with is this:</p>
<blockquote><p>$1 on Apple&#8217;s App Store is 89¢ on Kindle and 23¢ on Android</p></blockquote>
<p>What&#8217;s interesting is that Amazon is able to get the value proposition for developers into the vicinity of where it is for us iOS developers. Well it certainly helps to have the marketing experience of the world&#8217;s largest retailer and a dedicated device that locks people into their marketplace. And it still gives us a warm and fuzzy feeling that we are focussing on the app store where the most money is made. Our grass is greenest, yeah!</p>
<p>Here&#8217;s another good reason why we developers should always buy the latest Apple devices. An iOS forensics company has created a tool that lets law enforcement officials <a href="http://www.forbes.com/sites/andygreenberg/2012/03/27/heres-how-law-enforcement-cracks-your-iphones-security-code-video/">find out your passcode lock</a>. There&#8217;s a video where you can see them boot an iPhone with their own custom boot loader. iPhone hacker Chronic has told me that iOS devices with an A5 chip are safe.</p>
<blockquote><p>A5 devices can be jailbroken on a per-firmware basis, but their exploit(s) are userland-level, so passcode lock is safe.</p></blockquote>
<p>That means you should have no less than an iPhone 4S if you are worried about that the law or some lawless thugs who got hold of this software can decrypt all your secrets. Hey, it&#8217;s a business expense and of course we need proper test devices for our jobs.</p>
<p>Speaking of security, the Australian Department of Defence has <a href="http://www.dsd.gov.au/publications/iOS_Hardening_Guide.pdf">published a PDF</a> that treats in great details all the security aspects involved in using iOS devices in official agencies. It&#8217;s a great manual to have and pass on to IT guys who are evaluating use of iOS devices in the enterprise, it contains background information as to which questions you should ask from government contractors whose apps are to be used on those Secret Agent devices. Conversely if you ARE such a developer who is interested in the vertical market of government software then this guide contains all the questions that you probably will be asked. So you can prepare yourself accordingly, and have your apps be secure by design.</p>
<p>If you are looking for iOS or Mac developers for your compony or are looking for employment as such then I&#8217;d like to draw your attention to my new hobby project. I wanted to have a blog &#8211; combined with Twitter feed &#8211; where you could get the pulse of our industry. Though I don&#8217;t want to have any extra work, so I made it such that if you create a login on XcodeJobs.com you can write a short blog post about the positions you are trying to fill. This I can then publish very early. If that is too much effort for you then you can also tweet me a link to the job profile on your own site and I&#8217;ll retweet it with the @XcodeJobs twitter account.</p>
<p>This is completely non-commercial and Recruiter-free. When I was looking for a name for this baby I realized that all my favorite platforms we use Xcode to develop for. And since the name was free I grabbed it. If I hear from Apple&#8217;s legal department I can always change it later. But they say: &#8220;we&#8217;ll cross this bridge when we get to it&#8221;. Right now there are record numbers of people tweeting about the site and following the Twitter account. So why not benefit from this attention too?</p>
<p>Oh and speaking of hiring. I have hired my first actual real employee! And it&#8217;s great! He&#8217;s going to start working with us next month and I can already feel our output increase. Many iOS developers shy away from this sort of commitment, OMG how much that costs. What if you don&#8217;t have any work any more? But the reality is, that work always grows larger and larger and frankly I cannot afford to pay for contractors. At the current rates an employee costs me about a third as much as a contractor based in USA or Europe.</p>
<h3>Guest: Appsfire Co-Founder Ouriel Ohayon</h3>
<p>We chat about why there is a need for a UDID-replacement and what is is used for.<br />
Appsfire App <a href="http://itunes.apple.com/us/app/appsfire-discover-best-free/id366968540?mt=8">on the App Store</a></p>
<h3>Feedback</h3>
<p>I love to hear from you, you can email me at oliver@cocoanetics.com or tweet me @cocoanetics. If you want to give me audio feedback or have some interesting comment for me to play on the show please call my Google Voice mailbox:  <strong>(415) 860-4324</strong></p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6146&amp;md5=a29a09d778ebd684c9d86549407ebcee" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/03/podcast-31-udid-fire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.cocoanetics.com/files/Cocoanetics_031.mp3" length="45777215" type="audio/mpeg" />
		<atom:link rel="payment" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;popout=1&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F03%2Fpodcast-31-udid-fire%2F&amp;language=en_GB&amp;category=text&amp;title=Podcast+%2331+%26%238211%3B+%26%238220%3BUDID+Fire%26%238221%3B&amp;description=Episode+31%2C+recorded+Saturday+March+31st%2C+2012+%26%238211%3B+UDID+FIre+Mach+ado+about+UDID%2C+jobs+for+iOS+developers+abound+and+my+guest+today+is+Appsfire+Co-Founder+Ouriel+Ohayon.+%26nbsp%3B+News...&amp;tags=blog" type="text/html" />
	</item>
	</channel>
</rss>

