<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Tewha.net</title>
    <link>https://tewha.net/tags/ios-development/</link>
    <description>Recent content on Tewha.net</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 29 Jan 2026 18:30:42 +0000</lastBuildDate>
    <atom:link href="https://tewha.net/tags/ios-development/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Free Trials</title>
      <link>https://tewha.net/2026/01/free-trials/</link>
      <pubDate>Thu, 29 Jan 2026 18:30:42 +0000</pubDate>
      <guid>https://tewha.net/2026/01/free-trials/</guid>
      <description>&lt;p&gt;Late last night, I received a rejection for an update to my app, FretSketch (&lt;a href=&#34;https://apps.apple.com/app/fretsketch/id6752662475&#34;&gt;App Store&lt;/a&gt;). FretSketch is an app for displaying guitar chord voicings offline. I wrote it because I am still learning to play the ukulele. I know a lot of chord shapes for the soprano, but the baritone is tuned differently, and the shapes are not the same. I wanted something in my pocket that understood that.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Late last night, I received a rejection for an update to my app, FretSketch (<a href="https://apps.apple.com/app/fretsketch/id6752662475">App Store</a>). FretSketch is an app for displaying guitar chord voicings offline. I wrote it because I am still learning to play the ukulele. I know a lot of chord shapes for the soprano, but the baritone is tuned differently, and the shapes are not the same. I wanted something in my pocket that understood that.</p>
<blockquote>
<p><strong>Update:</strong> There&rsquo;s a couple updates to this at the end, including that Apple has accepted my appeal and approved the 1.2 update as-is. That changes nothing about the StoreKit bug, FB21795992, and Apple Creator Studio going so hard trying to trick the user into a &ldquo;free&rdquo; subscription.</p>
</blockquote>
<p>I was excited about this 1.2 release, as it checked off one of the major features I wanted to ship the first version with: a voicing tone analysis, which would tell you why you might prefer one particular fingering of a chord.</p>
<p>Why? Well, maybe this easier one is missing an important pitch class, or maybe it has an extra one. Consider an easily explained but probably poor example: a C power chord, for instance. It should have C, G, and nothing else. Maybe a common fingering also has an E. That makes it not a C power chord, but it may appear as one anyway in some references. Depending on the context within the song, you may not care about that E.</p>
<p>The point, since you likely don&rsquo;t care about any of that, is that I&rsquo;m <strong>really</strong> excited about this release.</p>
<p>The 1.2 update has been approved twice already, but both times I found bugs that I didn&rsquo;t want to ship. I really loathed rejecting the second one: without a fix users would need to re-select their instrument when they upgraded.</p>
<p>Apple&rsquo;s rejection fell under section 3.1.2, on Business — Payments — Subscriptions:</p>
<blockquote>
<p>One or more auto-renewable subscriptions are marketed in the purchase flow in a way that may mislead or confuse users about the subscription terms or pricing. Specifically:</p>
<ul>
<li>The auto-renewable subscription promotes the free trial, introductory pricing, or introductory period for the subscription more clearly and conspicuously than the billed amount.</li>
</ul>
</blockquote>
<p>Here&rsquo;s what it looks like:</p>
<p><img src="original.png" alt="original"></p>
<p>This is a screen that&rsquo;s been unchanged since 1.0. Honestly, I actually agree with them. The wrong thing is emphasized here. <strong>Free</strong> is big. <strong>$4.99/year</strong> is smaller. This is misleading.</p>
<p>The styling and text here is provided by Apple, not me.</p>
<p>If this styling and text is unacceptable to Apple, they should fix it in their own code.</p>
<h3 id="the-problem">The Problem</h3>
<p><strong>Try It Free</strong> is not an appropriate title here. It&rsquo;s misleading people into starting a subscription that they&rsquo;re going to be charged for. Here&rsquo;s the catch, though: <strong>App developers like me don&rsquo;t control that text.</strong></p>
<p>Instead, we specify information about the subscription in App Store Connect.</p>
<p>In this case:</p>
<ul>
<li>It&rsquo;s a yearly subscription.</li>
<li>It includes a one-week free trial.</li>
</ul>
<p>If you use <code>SubscriptionStoreView(groupID:)</code> to present the store, a lot of the presentation details are automatic. But here:</p>
<ul>
<li>&ldquo;FretSketch Full,&rdquo; the icon, and the bullet list are my code.</li>
<li>The Terms of Service and Privacy Policy are Apple&rsquo;s code and presentation, though I provide URLs and ask Apple to make them appear.</li>
<li>The subscription controls are largely Apple&rsquo;s, based on my configuration in App Store Connect.</li>
<li>I did specify that I want multi-line buttons, which can be <strong>really</strong> explicit about the deal.</li>
</ul>
<p>This screen is the result of that: Some combination of SwiftUI and StoreKit builds the button labels, styles them, and presents them without me having additional controls. In this case, it went with <strong>Try It Free</strong> and <strong>1 week free, then $4.99/year</strong>. I would&rsquo;ve preferred to have it say Subscribe, but I can&rsquo;t do that.</p>
<p>Apple has a few things I can control, though: The big one is <code>.subscriptionStoreButtonLabel()</code>. Here, I&rsquo;m using <code>.multiline</code>. It&rsquo;s not documented in Apple&rsquo;s reference, but there is a comment in the header file:</p>






<pre tabindex="0"><code>/// A button label that prefers to display two lines.</code></pre>
<p>Note it doesn&rsquo;t say anything about what kind of details. It certainly isn&rsquo;t documented to be misleading, though it is.</p>
<p>There are a few alternatives, but the only one that looks like it might satisfy them is using <code>.price</code>. With that, the button text becomes <strong>1 week free, then $4.99/year</strong>. I absolutely loathe this, since it&rsquo;s not an action. It&rsquo;s a rambling description. An action is something like <strong>Purchase</strong>, <strong>Try It</strong>, or <strong>Subscribe</strong>, right? <strong>1 week free, then $4.99/year</strong> isn&rsquo;t an action, it&rsquo;s a ramble. I looked through all of these options back in October; <code>.multiline</code> was the least terrible one, but they all suck.</p>
<h3 id="apples-solution">Apple&rsquo;s Solution</h3>
<p>It was at this point I wondered how Apple handles this in their own apps.</p>
<p>Let&rsquo;s take a look at how Apple solves this problem in Apple Creator Studio, released <strong>earlier this week</strong>. This should be fully compliant with Apple&rsquo;s latest standards, right?</p>
<p>It&rsquo;s really not. I was angry last night. Now I&rsquo;m just amused.</p>
<p><img src="creator-studio.jpeg" alt="Creator Studio"></p>
<p>This is worse than FretSketh. They don&rsquo;t even put the price <em><strong>in</strong></em> the button, though Free is in there. The price is left as secondary text, medium grey on a light grey background; much less prominent than the word Free.</p>
<p>They&rsquo;re also charging $215/year in Canada, which is 43x what I&rsquo;m charging. I should probably bump my price a little; I was originally planning to charge $0.99/month or $9.99/year, but went with an introductory price of half of that.</p>
<p>You can&rsquo;t use examples of other apps, even Apple&rsquo;s, to appeal an App Store rejection. Further, I wouldn&rsquo;t want this to be the reason they approve the misleading button title. But Apple&rsquo;s paywall should not have happened, and it would not have passed their own review process. Mine is subtly misleading through no fault of my own because Apple coded it so and judged it (fairly) as unworthy. That screen, though, is intentionally misleading.</p>
<p>Maybe that should be fine. Maybe they should just allow this. But when I say I want to be held to the same standard, I don&rsquo;t want it to be this sketchy one.</p>
<p>I could say something like &ldquo;it&rsquo;s good to be the king,&rdquo; but I don&rsquo;t think that&rsquo;s true. I think not being held to their own standards is going to be detrimental to them. Apple, stop being so sketchy.</p>
<h3 id="my-solution">My Solution</h3>
<p>First, I&rsquo;ve already appealed to App Review. I don&rsquo;t expect that to go anywhere they&rsquo;re fundamentally correct. This is misleading UI. I don&rsquo;t think &ldquo;but the misleading is coming from your code, Apple!&rdquo; is a great defence when it can be worked around.</p>
<p>You could be forgiven for asking &ldquo;Why are your screenshots so terrible?&rdquo; Remember I mentioned above that this stuff is configured in App Store Connect? The way to control the button title is to change the parameters in App Store Connect.</p>
<p>As I was writing this, Apple changed those parameters by removing my free trial. It&rsquo;s not quite as egregious as it seems since I mentioned I was willing to drop the free trial to fix this. I still wish they&rsquo;d asked, or better yet just acknowledged this was their problem. Other developers get to offer free trials, why can&rsquo;t I? Then again, they haven&rsquo;t sent a reply yet, so they <em>could</em> just be experimenting to see if what I&rsquo;m saying is true. Maybe they&rsquo;ll put it back and just didn&rsquo;t think I&rsquo;d notice.</p>
<p>But this morning I read on Reddit about <a href="https://www.reddit.com/r/iOSProgramming/comments/1qq6o5u/swiftui_tip_the_subscriptionstorecontrolstyle">another customization axis for sheets</a>: <code>.subscriptionStoreControlStyle()</code>. The default is <code>.prominentPicker</code>, which is what I&rsquo;m using. Most of the options are &ldquo;pickers,&rdquo; and they <strong>all</strong> have this same problem: StoreKit generates button titles that Apple will reject.</p>
<p>There&rsquo;s <strong>just one option</strong> that&rsquo;s not a &ldquo;picker,&rdquo; though, which is <code>.buttons</code>. That one shows the title of my subscription as the button, like this:</p>
<p><img src="buttons-multiline.png" alt="Multiline Buttons"></p>
<p>If I remove the <code>.multiline</code> setting, it actually gets even better.</p>
<p><img src="buttons-default.png" alt="Default Buttons"></p>
<p>I like this better. &ldquo;Free&rdquo; doesn&rsquo;t appear anywhere on the button, and with all the subscription details with the same prominence I think it would probably pass App Review. This is better than the appearance in FretSketch 1.0, and it&rsquo;s certainly better than what Apple does in Creator Studio.</p>
<p>Going forward:</p>
<ol>
<li>If Apple approves 1.2 as is on appeal, I&rsquo;ll ship it. I want this release in the hands of users.</li>
<li>If Apple removes the free trial to &ldquo;fix&rdquo; the button text, I&rsquo;ll ship 1.2 as is. I like a free trial, but I&rsquo;m not going to hold the release for this.</li>
<li>The next build, whether 1.2, 1.2.1 or 1.3, will switch to <code>.buttons</code> control style and default labels. It&rsquo;ll re-add the trial, but probably with a longer duration.</li>
<li>I&rsquo;m calling on Apple to fix StoreKit. That button should be titled <strong>Subscribe</strong>, not <strong>Try It Free</strong>. Even if they do that in a future version of iOS, though, it won&rsquo;t impact iOS versions already out there. I filed this as FB21795992. If this App Reviewer was correct, if you use any control style but <code>.buttons</code> in your app with an intro period you&rsquo;re risking rejection.</li>
<li>I&rsquo;m also calling on Apple to make Apple Creator Studio more honest. I don&rsquo;t want Apple to be sketchy like that, and I certainly don&rsquo;t want <em><strong>that</strong></em> to be our new standard. If you can help get the word out, please do!</li>
</ol>
<p><strong>Update:</strong> Apple has approved the Mac version. It uses the same code and store design. I have not released, because I want to do a simultaneous release.</p>
<p><img src="mac.png" alt="Mac 1.2"></p>
<p><strong>Update 2:</strong> On appeal, the iOS build was approved as-is. I still believe that <strong>Try It Free</strong> is a StoreKit bug, and Apple Creator Studio goes way over the line with its intentionally subservient pricing information and <strong>Accept Free Trial</strong>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Introducing FretSketch</title>
      <link>https://tewha.net/2025/11/introducing-fretsketch/</link>
      <pubDate>Sun, 09 Nov 2025 07:41:48 +0000</pubDate>
      <guid>https://tewha.net/2025/11/introducing-fretsketch/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve released a new app on the App Store: FretSketch! It&amp;rsquo;s an application for displaying chord fingering diagrams for the guitar or ukulele.&lt;/p&gt;
&lt;p&gt;It includes chords for standard guitar, low and high G standard ukulele, and baritone ukuleles.&lt;/p&gt;
&lt;p&gt;I picked what I hope is a humane way to monetize it: You can access anything int the app, but some of the features are behind a delay. So you can use any feature in the app and subscribe to remove the delay.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve released a new app on the App Store: FretSketch! It&rsquo;s an application for displaying chord fingering diagrams for the guitar or ukulele.</p>
<p>It includes chords for standard guitar, low and high G standard ukulele, and baritone ukuleles.</p>
<p>I picked what I hope is a humane way to monetize it: You can access anything int the app, but some of the features are behind a delay. So you can use any feature in the app and subscribe to remove the delay.</p>
<p>It&rsquo;s available on the <a href="https://apps.apple.com/us/app/fretsketch/id6752662475">App Store</a>. I&rsquo;ve also got <a href="https://hive604.com/products/fretsketch/">a very basic website for it</a> which includes a support link.</p>
<p>As a developer, there are some things I&rsquo;m particularly proud of:</p>
<ol>
<li>This is my first entirely SwiftUI app.</li>
<li>I really like the way the animation on the key selector wheel turned out.</li>
<li>I like the chord player, both the animations and the sound.</li>
</ol>
<p>Anyway, please check it out. Send me feedback if you have any, write a review if you feel like it, and subscribe if the app is useful to you.</p>
]]></content:encoded>
    </item>
    <item>
      <title>App Store Subscription Tips</title>
      <link>https://tewha.net/2025/10/app-store-subscription-tips/</link>
      <pubDate>Tue, 14 Oct 2025 17:06:49 +0000</pubDate>
      <guid>https://tewha.net/2025/10/app-store-subscription-tips/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m currently trying to get a subscription to my app working in the Sandbox App Store storefront.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what I&amp;rsquo;ve learned so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Subscriptions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subscription Localizations are not marked as required, but you need at least one or you&amp;rsquo;ll get &amp;ldquo;Status: missing metadata&amp;rdquo; when viewing the subscription. Although App Store Connect typically shows errors for missing data, it doesn&amp;rsquo;t in this case.&lt;/li&gt;
&lt;li&gt;Additionally, you need screenshots for the Review Information. App Store Connect at least warns you about this, but they seem completely useless to any purpose but completing metadata. Thanks to &lt;a href=&#34;https://mastodon.social/@bigzaphod&#34;&gt;Sean Heber&lt;/a&gt; for mentioning this; I forgot to put it on the list of recent pain. A lot has happened in the last couple of days.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Subscription Groups&lt;/strong&gt;:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;m currently trying to get a subscription to my app working in the Sandbox App Store storefront.</p>
<p>Here&rsquo;s what I&rsquo;ve learned so far:</p>
<ul>
<li>
<p><strong>Subscriptions:</strong></p>
<ul>
<li>Subscription Localizations are not marked as required, but you need at least one or you&rsquo;ll get &ldquo;Status: missing metadata&rdquo; when viewing the subscription. Although App Store Connect typically shows errors for missing data, it doesn&rsquo;t in this case.</li>
<li>Additionally, you need screenshots for the Review Information. App Store Connect at least warns you about this, but they seem completely useless to any purpose but completing metadata. Thanks to <a href="https://mastodon.social/@bigzaphod">Sean Heber</a> for mentioning this; I forgot to put it on the list of recent pain. A lot has happened in the last couple of days.</li>
</ul>
</li>
<li>
<p><strong>Subscription Groups</strong>:</p>
<ul>
<li>Subscription Group Localizations are <em>also</em> not marked as required, but you need at least one or you&rsquo;ll get &ldquo;Status: missing metadata&rdquo; when viewing the <em><strong>subscription</strong></em>. That&rsquo;s not a mistake: the warning about missing data in Subscription Groups appears in Subscriptions, not Subscription Groups.</li>
<li>Getting account level banking information submitted (and accepted, it took much longer than 24 hours to process) changed my status from &ldquo;Missing metadata&rdquo; to &ldquo;Ready to Submit.&rdquo;</li>
</ul>
</li>
<li>
<p><strong>Other</strong></p>
<ul>
<li>You  need to specify &ldquo;Terms of service: (URL)&rdquo; at the end of your description when using Apple&rsquo;s service terms, even if you&rsquo;ve specified the terms of service in the appropriate field. I would love to know the rationale for this.</li>
</ul>
</li>
</ul>
<p>Overall, App Store Connect needs some small but meaningful usability improvements. It would be enormously helpful if it listed which metadata was missing (and ideally linked to where to set it) instead of just reporting &ldquo;Status: missing metadata&rdquo; or, worse, &ldquo;Preparing for submission.&rdquo;</p>
]]></content:encoded>
    </item>
    <item>
      <title>How to fix UITableView rows changing size</title>
      <link>https://tewha.net/2015/01/how-to-fix-uitableview-rows-changing-size/</link>
      <pubDate>Sat, 17 Jan 2015 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2015/01/how-to-fix-uitableview-rows-changing-size/</guid>
      <description>&lt;p&gt;Do you have an app where the row heights in a table view shift, especially when navigating away from a view controller?&lt;/p&gt;
&lt;p&gt;This seems to be an iOS bug and is caused by using autolayout within a table cell without a &lt;code&gt;tableView:estimatedHeightForRowAtIndexPath:&lt;/code&gt; method.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Do you have an app where the row heights in a table view shift, especially when navigating away from a view controller?</p>
<p>This seems to be an iOS bug and is caused by using autolayout within a table cell without a <code>tableView:estimatedHeightForRowAtIndexPath:</code> method.</p>
<p>If you do not implement this method, the UITableView will treat that as an estimated row height of ``. AutoLayout will panic and try to compensate for this, and you’ll still see an incorrect size. (I believe this to be the minimum size that it thinks would satisfy your content without any spacing and taking wrapping into account, but I’m not sure of this.) You see this bug in some of Apple’s apps, including Settings.</p>
<p>To fix it, you need to implement <code>tableView:estimatedHeightForRowAtIndexPath:</code> and return a rough estimate of the size of the row. iOS includes a constant for this, if you have no good estimate: <code>UITableViewAutomaticDimension</code>.</p>
<p>This may introduce a few other (minor) problems, as providing estimates can lead to views being poorly sized as you scroll. Apple discusses this in their documentation. If you are impacted by something like that, a <code>tableView:estimatedHeightForRowAtIndexPath:</code> that returns values closer to actual might help. That said, while I had problems from rough estimation on the <strong>simulator</strong> I’ve never noticed it on a real device. Seems like the logic is a bit different between them.</p>
<p>However:</p>
<ul>
<li>You should <strong>not</strong> attempt to calculate real height values. The entire point of this method is to short-circuit involved height calculation. It’s just unnecessary.</li>
<li>You should not attempt to cache heights returned by the real <code>tableView:heightForRowAtIndexPath:</code>, either. The values in that cache will be wrong when <strong>estimatedHeightForRowAtIndexPath</strong> is first called anyway; they’re really no better than <code>UITableViewAutomaticDimension</code>. And if you return ``, you’ll hit this bug.</li>
</ul>
<p>So what <em>should</em> you do? It really is this simple:</p>
<pre><code>- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}
</code></pre>
<p>And you’re done!</p>]]></content:encoded>
    </item>
    <item>
      <title>Learn Swift</title>
      <link>https://tewha.net/2014/06/learn-swift/</link>
      <pubDate>Mon, 09 Jun 2014 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2014/06/learn-swift/</guid>
      <description>&lt;p&gt;Jon Friskics suggets &lt;a href=&#34;http://venturebeat.com/2014/06/07/swift-is-great-but-you-should-still-know-objective-c-first/&#34;&gt;Swift is great, but you should still know Objective-C first&lt;/a&gt;. &lt;a href=&#34;http://www.loopinsight.com/2014/06/09/swift-is-great-but-you-should-still-know-objective-c-first/&#34;&gt;Dave Mark agrees.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let me give you a different opinion:&lt;/p&gt;
&lt;p&gt;No, newbie, you don’t need to learn Objective-C first. You’ll miss it from time to time and you might want to pick it up later, but it won’t help you much now. And it will color your thinking in a way that might hurt your understanding.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Jon Friskics suggets <a href="http://venturebeat.com/2014/06/07/swift-is-great-but-you-should-still-know-objective-c-first/">Swift is great, but you should still know Objective-C first</a>. <a href="http://www.loopinsight.com/2014/06/09/swift-is-great-but-you-should-still-know-objective-c-first/">Dave Mark agrees.</a></p>
<p>Let me give you a different opinion:</p>
<p>No, newbie, you don’t need to learn Objective-C first. You’ll miss it from time to time and you might want to pick it up later, but it won’t help you much now. And it will color your thinking in a way that might hurt your understanding.</p>
<h2 id="arc_an_admittedly_imperfect_analogy">ARC, an admittedly imperfect analogy</h2>
<p>Let me rewind a few years. Apple introduced Automatic Reference Counting, which let the compiler manage its own memory. To this day, people continue to suggest you learn manual release/retain (MRR) before using ARC. I used MRR for years, and it really didn’t help me learn ARC. What helped me was understanding the object graph model, which was actually <em>hidden</em> by MRR. I think knowing MRR can actually make it <em>harder</em> to learn ARC.</p>
<p>So should you learn MRR <em>first</em>? No. You should learn the concepts behind good memory management on iOS — something many programmers never learned under MRR — then apply them to ARC. MRR is mostly unrelated to this.</p>
<p>To any MRR people who just read this and are shaking their heads: No, you really don’t need to know it. You and I know that this chunk of code is slow because it’s doing extra retains and releases, but the ARC user might instead know it’s because they’re assigning a strong reference. And the funny thing is that’s probably a better way to think of it.</p>
<p>And none of this is to suggest that’s not to say people it isn’t helpful to learn MRR. MRR offfers a better perspective on some concepts, such as <a href="https://alpha.app.net/jws/post/32225169"><code>__autoreleasing</code>, bridge casts, precise lifetime, consumed parameters</a>. But I’m not at all convinced you need to learn MRR first, because I think the ARC concepts are generally more useful for a 5,000 foot view of what’s going on. When you’re hovering three feet over? Knowing MRR is great.</p>
<h2 id="swift">Swift</h2>
<p>Just looking at it and playing for a few minutes, I think Swift is another great example of this. Swift is a teaching language that’s probably more useful for day-to-day programming tasks than the language it replaces. It’s also likely to be more performant than Objective-C, thanks to… well, that’s another article. 🙂</p>
<p>If you’re a new developer reading this, ignore Friskics’s article. <strong>Get the concepts down</strong> and then <strong>learn the language you’re going to use</strong>. Enjoy it. You don’t have to suffer like we did. You get to start from our shoulders, and that’s a good thing. Nothing prevents you from learning down as well.</p>
<p>In a few years I’ll miss Objective-C. But primarily because I felt there was always something to learn about it, and a better way to write my code. I’m not sure if I’ll still have that feeling with Swift, but that nostalgia doesn’t mean Objective-C is a better language.</p>
<p>To address his points:</p>
<ol>
<li>You can learn the frameworks in Swift just as easily as Objective-C. Apple’s designed Swift to work this way, and their documentation is already ready.</li>
<li>Swift will be tried and true before you know it. This isn’t something Apple started working on the Tuesday before WWDC, and it’s not going final way off in 2016. Sure, Swift isn’t the main language yet, but it will be by the time you’re ready to ship something.</li>
<li>The learning materials and code examples are already appearing, and they’re going to continue to appear.</li>
<li>Just because you can mix languages if there’s a reason for it doesn’t mean you have to. Sure, we Objective-C programmers mix C code in if we have to. But it’s not the first thing we reach for.</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Debugging app upload</title>
      <link>https://tewha.net/2014/05/debugging-app-upload/</link>
      <pubDate>Fri, 02 May 2014 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2014/05/debugging-app-upload/</guid>
      <description>&lt;p&gt;I’ve had some recent troubles trying to upload a build in Xcode. These involved getting a really unhelpful error from Xcode: “No identities were available.” Unfortunately, I was stuck there for two days.&lt;/p&gt;
&lt;p&gt;It turns out that you can get Xcode to log more information on the handshake with the portal. Quit Xcode, then run these two commands.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I’ve had some recent troubles trying to upload a build in Xcode. These involved getting a really unhelpful error from Xcode: “No identities were available.” Unfortunately, I was stuck there for two days.</p>
<p>It turns out that you can get Xcode to log more information on the handshake with the portal. Quit Xcode, then run these two commands.</p>
<p>defaults write com.apple.dt.Xcode DVTCodesigningAllTheThingsLogLevel 3
defaults write com.apple.dt.Xcode DeveloperPortalLogLevel 3</p>
<p>Then, open Console. Quit anything spewing to it, clear the display, then try to upload your build again. When you’re done, select and copy the spew to Console and paste it into your favorite text editor. You’re looking for <code>DeveloperPortal</code> and <code>DVTCodesigningAllTheThings</code> rows.</p>
<p>The results aren’t exactly easy to interpret, but it does give you a better idea of what’s being reported to Xcode, as opposed to what Xcode displays. Xcode is probably simplifying the error message.</p>
<p>When you’ve solved your problem, you’ll probably want to turn it back off:</p>
<pre><code>defaults delete com.apple.dt.Xcode DVTCodesigningAllTheThingsLogLevel
defaults delete com.apple.dt.Xcode DeveloperPortalLogLevel
</code></pre>
<p>In my case, I solved my major problem literally seconds before I learned about this logging trick: I had used a bundle ID of <code>com.company.product</code>, whereas I was now using <code>com.company.${PRODUCT_NAME:rfc1034identifier}</code>. That made the effective bundle ID of the new product <code>com.company.Product</code>, which was enough that Xcode couldn’t find a corresponding application for my bundle. I don’t know what that would have looked like in the log.</p>
<p>This logging trick did solve me with a subsequent problem, however, by letting me know it was based on permissions. As a result, I spent only seconds on that one, and my app is now waiting in Apple’s review queue.</p>
<p>I don’t know if this will help you or not, but if you’re getting only a generic error message it’s worth a try.</p>]]></content:encoded>
    </item>
    <item>
      <title>On Frameworks</title>
      <link>https://tewha.net/2014/01/on-frameworks/</link>
      <pubDate>Wed, 15 Jan 2014 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2014/01/on-frameworks/</guid>
      <description>&lt;p&gt;A coworker sent me a link to &lt;a href=&#34;http://landonf.bikemonkey.org/code/ios/Radar_15800975_iOS_Frameworks.20140112.html&#34;&gt;this posting on the state of libraries on iOS&lt;/a&gt;. I sent back a quick reply, with the intent to write a blog post on the subject later.&lt;/p&gt;
&lt;p&gt;I’ve since decided that this replay says almost everything I wanted to say, so I decided to just edit it a bit.&lt;/p&gt;
&lt;p&gt;I’m pretty torn on this whole subject. Dynamic libraries can lead to inefficiencies in storage space if a developer isn’t careful, and I’ve no reason to believe iOS developers are careful. Include Google Toolbox for one function? Sure, why not? Apple’s always balanced the experience towards users, and even when it makes my life more difficult I like that.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>A coworker sent me a link to <a href="http://landonf.bikemonkey.org/code/ios/Radar_15800975_iOS_Frameworks.20140112.html">this posting on the state of libraries on iOS</a>. I sent back a quick reply, with the intent to write a blog post on the subject later.</p>
<p>I’ve since decided that this replay says almost everything I wanted to say, so I decided to just edit it a bit.</p>
<p>I’m pretty torn on this whole subject. Dynamic libraries can lead to inefficiencies in storage space if a developer isn’t careful, and I’ve no reason to believe iOS developers are careful. Include Google Toolbox for one function? Sure, why not? Apple’s always balanced the experience towards users, and even when it makes my life more difficult I like that.</p>
<p>The static library approach isn’t a good approach either. Sometimes I’ve had less than complete debugging info, and been missing information in crash logs. And its code stripping isn’t as good as it should be, either. The final straw for me was when <a href="http://hockeyapp.net/">HockeyApp’s crash reporter</a> stopped producing useful stack crawls. I spent a few hours trying to fix this, even got a little help (HockeyApp is excellent, and their support is outstanding) but quickly realized I was spending too much time on a problem with a very pragmatic fix.</p>
<p>(What was the problem? I’m not sure. It seemed to be related to an Xcode update, but after a few hours I grew less interested in solving it and more interested in shipping what was a critical update to my app.)</p>
<p><a href="http://cocoapods.org">Cocoapods</a> tries to solve this, but I think it does so the wrong way. You still have the same problems, it’s just a little less trouble to keep it going. It’s probably better than nothing, but it wasn’t the approach I wanted to take.</p>
<p>What I’ve been doing recently is including the sources in groups within my project. This is harder for me, but better for the compiler/linker (it has a better sense of everything I’m trying to do), debugger (all the symbol information is built as part of the main project) <strong>and</strong> the end user (who gets a better stripped executable).</p>
<p>What we need is not static libraries or dynamic libraries or frameworks. We need something better, more tuned to iOS.</p>
<p>There’s a few options:</p>
<ul>
<li>A project include file, which lets you specify a source group to build but is linked into the main project. This has the advantage of being linked separately.</li>
<li>A <em>dynamic</em> dynamic library, where the library is built by the main project based on the subproject with an understanding of what parts of library the main project uses.</li>
</ul>
<p>Until Apple has a good solution to this, I’m going to continue to avoid static libraries (except for very specific libraries, like HockeyApp) and put the sources in a group.</p>
<p>I really hope Apple comes up with a good solution soon, though. This is indeed painful. I think Landon’s radar is entirely positive; Apple isn’t too likely to just do the easy thing. They’ll think about, evaluate possibilities, then do something that we can hopefully live with. Hopefully something better than any of us anticipated.</p>]]></content:encoded>
    </item>
    <item>
      <title>Change back button title</title>
      <link>https://tewha.net/2013/10/change-back-button-title/</link>
      <pubDate>Thu, 17 Oct 2013 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/10/change-back-button-title/</guid>
      <description>&lt;p&gt;When you’re using a navigation controller, the title of the back button on a particular view controller is pulled from the view it leads to.&lt;/p&gt;
&lt;p&gt;Although this can be initially confusing, this actually makes a lot of sense. If two different view controllers (say, Circles and Squares) might push the same view controller (Details), shouldn’t the text in the top left of that view controller depend on which controller pushed it (Circles or Squares)?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>When you’re using a navigation controller, the title of the back button on a particular view controller is pulled from the view it leads to.</p>
<p>Although this can be initially confusing, this actually makes a lot of sense. If two different view controllers (say, Circles and Squares) might push the same view controller (Details), shouldn’t the text in the top left of that view controller depend on which controller pushed it (Circles or Squares)?</p>
<p>Think of it this way:</p>
<pre><code>thisViewController.visibleBackButtonTitle =
    previousViewController.navigationItem.backBarButtonItem.title
    ?: previousViewController.navigationItem.title
    ?: previousViewController.title;
</code></pre>
<p>This won’t compile; <code>visibleBackButtonTitle</code> doesn’t actually exist.</p>
<p>There are a few reasons to show custom text on the back button.</p>
<h2 id="more_generic">More generic</h2>
<p>The most obvious reason is that your title relies on user input that may be too long, and you want something simpler and more generic.</p>
<p>This might be the case if the user taps an event. The title in the navigation controller should be the event’s title, but you might want to use something shorter like Event on the back button.</p>
<p>This case is simple: select the parent view controller and give it a custom <strong>Back Button</strong> value.</p>
<h2 id="more_specific">More specific</h2>
<p>You might also have the opposite problem, where your context is not visible in the navigation title because it’s obvious from something else in the view controller. But you still want to leave that more specific title as a breadcrumb for the user.</p>
<p>An example of this might be an address without a label. The first line of the address doesn’t make sense as a navigation title, as it duplicates the view. But if you tap deeper than that, you might want to include <em>something</em> about the address, such as the house number of the position in the list.</p>
<p>This is a little more complicated. You’ll need to do this at runtime: Set the <code>title</code> of the <code>backBarButtonItem</code> for the navigation item of the view controller the button leads to. That will prevent the navigation item’s <code>title</code> from being used.</p>
<p><strong>But there’s a wrinkle.</strong> Let’s assume you want to set the title dynamically. You might have something like this in your parent view controller, which is called by your <code>viewWillAppear</code> and whatever triggers updates of the view controller:</p>
<pre><code>- (void)loadData {
    // lots of other stuff
    self.navigationItem.backBarButtonItem.title = @&quot;dynamic title&quot;;
}
</code></pre>
<p>This probably isn’t going to work for you as is.</p>
<p>You’ll find lots of crazy solutions to this; manipulating the <code>backBarButtonItem</code> by hand and restoring it after for instance. (There are much, much crazier solutions.)</p>
<p>The key is understanding why it’s not working: <code>backBarButtonItem</code> is <code>nil</code>.</p>
<p>To make it not <code>nil</code>, you have two options:</p>
<ol>
<li>Select the navigation item in the storyboard editor and give <strong>Back Button</strong> a value. This value will cause the <code>backBarButtonItem</code> to be automatically created with the view controller is instantiated.</li>
<li>Create the <code>backBarButtonItem</code> at runtime in your <code>viewDidLoad</code> or <code>awakeFromNib</code> (<a href="https://twitter.com/calebd/status/391068542076207105">suggested by @calebd</a>). I don’t recommend doing this in code; you’re already using a storyboard or nib, so it’s much simpler to just put a <strong>Back Button</strong> value into your view controller.</li>
</ol>
<p>Once it’s created — whether in code or by storyboard — its title can be changed. You can change <code>backBarButtonItem</code>’s title at any time when the parent is displayed, as often as you like: it’ll only be shown when you push something else on top of it.</p>
<h2 id="summary">Summary</h2>
<p>If the text is always the same:</p>
<ol>
<li>Select the parent view controller’s <strong>Navigation Item</strong> in the editor.</li>
<li>Put the text into the <strong>Back Button</strong> value.</li>
</ol>
<p>If the text is dynamic:</p>
<ol>
<li>Select the parent view controller’s <strong>Navigation Item</strong> in the editor.</li>
<li>Put <em>some</em> text into the <strong>Back Button</strong> value.</li>
<li>Set the title in the <em>parent</em> view controller, when its contents change: <code>self.navigationItem.backBarButtonItem.title = dynamicText;</code></li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Check your thread</title>
      <link>https://tewha.net/2013/03/check-your-thread/</link>
      <pubDate>Wed, 06 Mar 2013 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/03/check-your-thread/</guid>
      <description>&lt;p&gt;When you start using Grand Central Dispatch or &lt;code&gt;NSOperation&lt;/code&gt;, you’ll want to perform some actions on the main thread and some intentionally off the main thread.&lt;/p&gt;
&lt;p&gt;This is a simple and obvious technique, but it took me a while to adopt it: You can do by asserting with &lt;code&gt;NSAssert&lt;/code&gt; or &lt;code&gt;NSCAssert&lt;/code&gt; for &lt;code&gt;[NSThread isMainThread]&lt;/code&gt;, just as you would assert any other condition.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>When you start using Grand Central Dispatch or <code>NSOperation</code>, you’ll want to perform some actions on the main thread and some intentionally off the main thread.</p>
<p>This is a simple and obvious technique, but it took me a while to adopt it: You can do by asserting with <code>NSAssert</code> or <code>NSCAssert</code> for <code>[NSThread isMainThread]</code>, just as you would assert any other condition.</p>
<p>Like this:</p>
<pre><code>- (void)updateUI {
    NSAssert([NSThread isMainThread], @&quot;Only update UI from main thread&quot;);
    // update UI
}

- (void)backgroundWork {
    NSAssert(![NSThread isMainThread], @&quot;Only do work off main thread&quot;);
    // do work
}
</code></pre>
<p>With assertions like this in place, you’ll sort out what executes where in short order.</p>
<p>I wish I had done this to my code right away; it’s much simpler to get it right than to go back and fix it all later.</p>]]></content:encoded>
    </item>
    <item>
      <title>Presenting BlockAssert</title>
      <link>https://tewha.net/2013/02/presenting-blockassert/</link>
      <pubDate>Fri, 22 Feb 2013 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/02/presenting-blockassert/</guid>
      <description>&lt;p&gt;Assertions are a great tool. As an Objective-C programmer, I use &lt;code&gt;NSAssert&lt;/code&gt; and &lt;code&gt;NSCAssert&lt;/code&gt; liberally.&lt;/p&gt;
&lt;p&gt;For various reasons, you sometimes can’t use &lt;code&gt;NSAssert&lt;/code&gt; in a block easily. I’m going to explain why and describe a new macro, &lt;code&gt;BlockAssert&lt;/code&gt;, which solves this.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Assertions are a great tool. As an Objective-C programmer, I use <code>NSAssert</code> and <code>NSCAssert</code> liberally.</p>
<p>For various reasons, you sometimes can’t use <code>NSAssert</code> in a block easily. I’m going to explain why and describe a new macro, <code>BlockAssert</code>, which solves this.</p>
<h2 id="background">Background</h2>
<p>An assertion is a predicate (a true–false statement) placed in a program to indicate that the developer thinks that the predicate is always true at that place. (Source: <a href="http://en.wikipedia.org/wiki/Assertion_(computing)">Wikipedia</a>.)</p>
<p><code>NSAssert</code> and <code>NSCAssert</code> are Foundation’s assertion macros. They’re kind of like C’s assert macro, but provide an error message in the same form as <code>NSLog</code>. The difference between them is that <code>NSAssert</code> references <code>self</code>, which is only defined for Objective-C methods. <code>NSCAssert</code>, then, is <code>NSAssert</code> for C functions.</p>
<p>Blocks are often defined in Objective-C methods, but they’re not themselves Objective-C methods. Although they’re actually implemented as objects of their own, the syntax is more like a C functions. They don’t define self, though anything you want from the method scope are captured strongly into the block expression. This means that if you use <code>NSAssert</code> you’ll be capturing <code>self</code>. But that strong reference can cause a circular reference.</p>
<p>A circular reference is formed the block owns the object and the object owns something that owns the block. None of the memory will ever be cleaned up. Even you <em>do</em> clean up the memory, you’ll get a compiler warning that you need to ignore.</p>
<p>Rather than sort out which of these compiler warnings is valid, a lot of people use this pattern:</p>
<pre><code>__weak typeof(self) weakSelf = self;
foo.completionBlock = ^{
	__strong typeof(self) strongSelf = weakSelf;
    [strongSelf doSomething];
};
</code></pre>
<p>This breaks the circular reference, and because we’ve used <code>__weak</code> we’re assured that <code>weakSelf</code> is not a dangling pointer. If <code>self</code> no longer exists, <code>weakSelf</code> is <code>nil</code>. Reassigning back to a <code>__strong</code> variable presents the variable from being deallocated</p>
<p><em>In this case, it’s not actually necessary to assign <code>weakSelf</code> to a <code>__strong</code> variable. The recipient of a message won’t be deallocated until the message returns. However, if you are doing multiple things with <code>weakSelf</code> — such as doing assertions against it and sending it a message — it could become deallocated between those messages.</em></p>
<p>The catch? <code>NSAssert</code> still uses the <code>self</code> variable by name. This led to an interesting question on StackOverflow about <a href="http://stackoverflow.com/questions/14194600/is-typeofself-self-weakself-construction-legitimate-inside-block">defining a block-scope self</a>, a technique that’s valid but requires you to remember to do it every time and <a href="/2013/02/against-gcc_warn_shadow/">causes a warning if GCC_WARN_SHADOW is on</a>.</p>
<h2 id="a_new_assertion_macro">A new assertion macro</h2>
<p>In the past, I’ve mostly done avoided this by not using assertions in blocks. You don’t need them very often, as you can usually do your assertions in the method’s scope. But inspired by that question, I’ve found a better way: I define my own assertion macro.</p>
<p>I have several such macros I define, in a single file that’s imported in as part of my precompiled header.</p>
<p>The macro looks like this:</p>
<pre><code>#define BlockAssert(condition, desc, ...) 
    do { 
        __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS 
        if (!(condition)) { 
            [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd 
            object:strongSelf file:[NSString stringWithUTF8String:__FILE__] 
                lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; 
        } 
        __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS 
    } while(0)
</code></pre>
<p>This is basically a copy-paste of <code>NSAssert</code>, but uses <code>strongSelf</code> instead of <code>self</code>. (Note, however, that we have <em>not</em> pretended to be part of Foundation by using a NS prefix.)</p>
<p>To use <code>BlockAssert</code>, you need to use the <code>weakSelf = self; strongSelf = weakSelf;</code> pattern, but you probably already are. And if not, the compiler will throw an error: <strong>Use of undeclared identifier: ‘strongSelf’</strong>. You can either adopt <code>strongSelf</code> or switch over to <code>NSAssert</code>.</p>
<p>For example:</p>
<pre><code>- (IBAction)clickButton: (UIButton *)sender {
    sender.disabled = YES;
    [self performActionWithCompletion: ^{
        BlockAssert(state, @&quot;Invalid state&quot;);
        sender.disabled = NO;
    }];
}
</code></pre>
<h2 id="conclusion">Conclusion</h2>
<p>I think this is a pretty good approach: If you use <code>NSAssert</code> where you meant to use <code>BlockAssert</code> and it matters, you’ll get a warning about a potential circular reference. If you use <code>BlockAssert</code> where you meant to use <code>NSAssert</code>, you’ll probably get a compiler error.</p>]]></content:encoded>
    </item>
    <item>
      <title>Against GCC_WARN_SHADOW</title>
      <link>https://tewha.net/2013/02/against-gcc_warn_shadow/</link>
      <pubDate>Thu, 21 Feb 2013 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/02/against-gcc_warn_shadow/</guid>
      <description>&lt;p&gt;Over the years I have tweaked which compiler warnings I use. There’s one in particular that I used to turn on but will turn off from now on: &lt;code&gt;GCC_WARN_SHADOW&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GCC_WARN_SHADOW&lt;/code&gt; is essentially drawing your attention to you &lt;em&gt;possibly&lt;/em&gt; doing something other than you intended. This is like most warnings, but the difference is that the behaviour &lt;code&gt;GCC_WARN_SHADOW&lt;/code&gt; is blocking is very useful.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Over the years I have tweaked which compiler warnings I use. There’s one in particular that I used to turn on but will turn off from now on: <code>GCC_WARN_SHADOW</code>.</p>
<p><code>GCC_WARN_SHADOW</code> is essentially drawing your attention to you <em>possibly</em> doing something other than you intended. This is like most warnings, but the difference is that the behaviour <code>GCC_WARN_SHADOW</code> is blocking is very useful.</p>
<p>This is the sort of things the more paranoid compiler warnings are good at. The downside is that it’s difficult (not impossible) to drop a particular warning to indicate that you know what you’re doing.</p>
<p>With <code>GCC_WARN_SHADOW</code> on, this code will generate a warning:</p>
<pre><code>int a = 5;
int b = 3;
int c = 4;
int value = MAX(a,MAX(b,c));
</code></pre>
<p>Despite that, it will function perfectly. The reason for the warning is that it compiles down to this:</p>
<pre><code>({
   int __a = (a);
   int __b = (({
       int __a = (b);
       int __b = (c);
       __a &lt; __b ? __b : __a;
   }));
   __a &lt; __b ? __b : __a;
})
</code></pre>
<p>This is horribly ugly code. You wouldn’t want to write this code. You wouldn’t want to read it. But here’s the catch: it’s perfectly valid to the compiler, and hiding the ugliness <em>is why <code>MAX()</code> exists</em>.</p>
<p>There’s a few ways to avoid this. The first is to not use the <code>MAX()</code> macro at all:</p>
<pre><code>int a = 5;
int b = 3;
int c = 4;
int value = a &lt; b ? (b &lt; c ? c : b) : a;
</code></pre>
<p>Or, you could do this:</p>
<pre><code>int a = 5;
int b = 3;
int c = 4;
int temp = MAX(b,c);
int value = MAX(a,temp);
</code></pre>
<p>If you’re interested in <code>temp</code> — if it’s a value that has meaning — this is a fine approach. Give it a better name than <code>temp</code> and run with it. But if it’s a value that has no meaning other than an uninteresting temporary variable on your way to <code>value</code>, you’ve made your code worse.</p>
<p>Next up, you could turn off the warning:</p>
<pre><code>int a = 5;
int b = 3;
int c = 4;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored &quot;-Wshadow&quot;
int value = MAX(a,MAX(b,c));
#pragma GCC diagnostic pop
</code></pre>
<p>This last method can be simplified (a little):</p>
<pre><code>#define PUSH_NOSHADOW _Pragma(&quot;GCC diagnostic push&quot;) _Pragma(&quot;GCC diagnostic ignored &quot;-Wshadow&quot;&quot;)
#define POP_NOSHADOW _Pragma(&quot;GCC diagnostic pop&quot;)
int a = 5;
int b = 3;
int c = 4;
PUSH_NOSHADOW
int value = MAX(a,MAX(b,c));
POP_NOSHADOW
</code></pre>
<p>This last technique suggests permanent fix: Apple could change the definition of MAX to avoid this (10296999).</p>
<p>But really? Just stop using <code>GCC_WARN_SHADOW</code>. It’s an unnecessary pain in the ass.</p>
<p>These are artificial examples, granted. But let’s pull this back to Objective-C, and something a typical Cocoa or Cocoa Touch programmer might have to do:</p>
<p>Also, if you use this you’ll need to name error variables in blocks differently:</p>
<pre><code>NSError *e;
[self somethingWithError: &amp;e];
[self runWithCompletion:^{
    NSError *e;
    [self recoverFromError:&amp;e]; // warning, or rename inner error to e2
}];
</code></pre>
<p>Overall, I didn’t think it was worth the extra effort anymore. Your mileage will (of course) vary.</p>]]></content:encoded>
    </item>
    <item>
      <title>Reachability</title>
      <link>https://tewha.net/2012/10/reachability/</link>
      <pubDate>Thu, 18 Oct 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/10/reachability/</guid>
      <description>&lt;p&gt;Apple has a sample code package called Reachability. It wraps an iOS framework called SystemConfiguration, and can be used to determine network status, and catch events about networking going up and down. In the past, it’s been an ugly chunk of sample code, but it’s pretty respectable now.&lt;/p&gt;
&lt;p&gt;One thing Reachability is not, however, is a crystal ball. Please don’t use it as if it were.&lt;/p&gt;
&lt;p&gt;In this article, I’m going to discuss how to use it. Because this is one thing I see a lot of developers get wrong.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Apple has a sample code package called Reachability. It wraps an iOS framework called SystemConfiguration, and can be used to determine network status, and catch events about networking going up and down. In the past, it’s been an ugly chunk of sample code, but it’s pretty respectable now.</p>
<p>One thing Reachability is not, however, is a crystal ball. Please don’t use it as if it were.</p>
<p>In this article, I’m going to discuss how to use it. Because this is one thing I see a lot of developers get wrong.</p>
<p>How should you use Reachability?</p>
<ol>
<li><strong>Always try your connection <em>first</em>.</strong> If you need to upload a change to the server, go ahead and try it. Don’t worry about what Reachability last said, or currently says. Your attempt may be what kicks iOS into powering up the wireless hardware or re-establishing a connection. Networking is really hard; the only way to know if your connection will succeed is to try it and see if it <strong>did</strong> succeed.</li>
<li><strong>Use Reachability to diagnose a connection failure.</strong> Reachability can’t tell you if your request will succeed, but if your request fails Reachability probably accurately reflects the reason why. Use what it tells you to improve your reporting to the user.</li>
<li><strong>Use Reachability to retry when the connection goes back online.</strong> Something else may provoke iOS into powering up the wireless hardware, and it may succeed. When this happens, Reachability will send out a notification. It’s absolutely appropriate to use this notification to retry your networking.</li>
<li><strong>Don&rsquo;t stop the user from trying networking anyway.</strong> Even if you think the device is offline, you should still allow the user to attempt actions that require a network connection.</li>
</ol>
<p>Reachability is a great tool, but it’s a tool for particular tasks. Learn the tasks Reachability is suited to, and your app will be better for it. You wouldn’t use a hammer to change a light bulb. Please don’t use Reachability to determine if a connection will fail.</p>]]></content:encoded>
    </item>
    <item>
      <title>View Controller Lifecycle in iOS 6</title>
      <link>https://tewha.net/2012/10/view-controller-lifecycle-in-ios-6/</link>
      <pubDate>Thu, 04 Oct 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/10/view-controller-lifecycle-in-ios-6/</guid>
      <description>&lt;p&gt;I previously wrote about breaking the old pattern of &lt;a href=&#34;https://tewha.net/2012/09/dont-write-viewdidunload/&#34;&gt;writing viewDidUnload&lt;/a&gt;. The other half of that is the new reality, which Joe Conway’s written about in &lt;a href=&#34;http://thejoeconwayblog.wordpress.com/2012/10/04/view-controller-lifecycle-in-ios-6/&#34;&gt;View Controller Lifecycle in iOS 6&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I previously wrote about breaking the old pattern of <a href="/2012/09/dont-write-viewdidunload/">writing viewDidUnload</a>. The other half of that is the new reality, which Joe Conway’s written about in <a href="http://thejoeconwayblog.wordpress.com/2012/10/04/view-controller-lifecycle-in-ios-6/">View Controller Lifecycle in iOS 6</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>How to avoid starting view controllers in the wrong orientation on startup</title>
      <link>https://tewha.net/2012/09/how-to-avoid-starting-view-controllers-in-the-wrong-orientation-on-startup/</link>
      <pubDate>Thu, 27 Sep 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/09/how-to-avoid-starting-view-controllers-in-the-wrong-orientation-on-startup/</guid>
      <description>&lt;p&gt;This is a bit obscure, but I ran into it earlier this week. Why would a view controller appear in the wrong orientation on startup?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This is a bit obscure, but I ran into it earlier this week. Why would a view controller appear in the wrong orientation on startup?</p>
<p>When your iPad application first launches it will be in portrait mode, even if it’s held in landscape mode. The rotate event is already in the queue and is consumed early enough that it’ll never actually be shown like that. So no problem, right?</p>
<p>The problem is that the rotate event will not have been consumed when your <code>viewWillAppear:</code> is first called. Opening a new view controller in <code>viewWillAppear:</code> (whether using <code>presentModalViewController:</code> or a storyboard segue) will open that new view controller in portrait mode, rather than landscape mode. Even that wouldn’t be a problem, except iOS will not add a rotate event added for the new view controller.</p>
<p>This all makes a great deal of sense when you think it through: The rotate events for the initial view controller or controllers are already on queue before <code>viewWillAppear</code> is called. iOS already recognizes the device has been rotated; as far as it’s concerned, the rotation is done. Your app is just lagging a bit behind as part of the startup process, with everything all queued up.</p>
<p>Conceptually, this is a hard problem.</p>
<p>But in practice, there’s a very simple and very elegant solution using blocks.</p>
<p>All you need to do is delay your view controller’s appearance. Before blocks, you might have had to use a timer. But now you can just use <code>dispatch_async</code> to schedule the new view controller for later.</p>
<p>That’s a little confusing, so here’s an example:</p>
<p>I have a view controller that appears when my application is first installed, to walk the user through the signup process. (Later, if there’s an authentication problem, I fall back on the standard username and password alert view.)</p>
<p>This view controller, then, needs to appear when my main view first appears. If I use this code, the view controller that appears will always be in portrait, even if the device is started in landscape.</p>
<pre><code>- (void)viewWillAppear: (BOOL)animated {
    [super viewWillAppear:animated];
    if (freshInstall) {
        [self performSegueWithIdentifier: @&quot;firstRun&quot; sender: self];
    }
}
</code></pre>
<p>If I use this code, however, the view controller that appears will match the device (and the view controller it’s appearing over):</p>
<pre><code>- (void)viewWillAppear: (BOOL)animated {
    [super viewWillAppear:animated];
    if (freshInstall) {
        dispatch_async(dispatch_get_main_queue(),^{
            [self performSegueWithIdentifier: @&quot;firstRun&quot; sender: self];
        });
    }
}
</code></pre>
<p>Later in this case is <em>still before</em> the user has a chance to interact, or even before the UI really and truly appears onscreen. The block for showing the view controller will be added to the queue. Everything will just work. By the time your block is run from the main queue, the rotation event will be dealt with and your app will really and truly be in landscape orientation. However, it’ll still be early enough for your view controller to look like part of early application startup.</p>
<p><em>Note: This was done on my “stable” branch, so it was probably on iOS 5. I have not yet tried this on iOS 6, but <a href="https://twitter.com/shusta/statuses/251389962661027842">I’ve read reports this is no longer necessary</a>. Either way, it’s a good trick if you plan on maintaining iOS 5 compatibility (which you should, for a while at least).</em></p>]]></content:encoded>
    </item>
    <item>
      <title>Make your library enforce ARC</title>
      <link>https://tewha.net/2012/09/make-your-library-enforce-arc/</link>
      <pubDate>Thu, 27 Sep 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/09/make-your-library-enforce-arc/</guid>
      <description>&lt;p&gt;If you have an open source library that requires Automatic Reference Counting (ARC), you may have issues with your users trying to build it without ARC turned on. Luckily, it’s pretty simple to &lt;em&gt;enforce&lt;/em&gt; ARC.&lt;/p&gt;
&lt;p&gt;I’m going to discuss how to do so, and why it’s a good idea.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>If you have an open source library that requires Automatic Reference Counting (ARC), you may have issues with your users trying to build it without ARC turned on. Luckily, it’s pretty simple to <em>enforce</em> ARC.</p>
<p>I’m going to discuss how to do so, and why it’s a good idea.</p>
<p>Here’s an example, which I submitted to AFNetworking:</p>
<pre><code>#if !__has_feature(objc_arc)
#error AFNetworking must be built with ARC.
// You can turn on ARC for only AFNetworking files by adding -fobjc-arc to the build phase for each of its files.
#endif
</code></pre>
<p>When the user builds the unit, the error will be highlighted. They’ll see the comment just below, explaining how to resolve the problem.</p>
<p>Adding it to every .m file may seem overkill, but there’s two good reasons for this:</p>
<ol>
<li>No matter which file gets compiled first an error will top the list instead of warnings. It’s sufficient to add it only to a central file, but you’ll probably still get support requests that way. You’re better off adding it everywhere; this is all about reducing your work.</li>
<li>ARC can be decided on a per-file basis. If you include it in only one file, the user may add -fobjc-arc to just that one file!</li>
</ol>
<p>But do not add this to your headers. Even if your code requires ARC, there’s no reason to require that the user’s code also use ARC. Apple did the right thing here.</p>]]></content:encoded>
    </item>
    <item>
      <title>Objective-C Feature Availability Index</title>
      <link>https://tewha.net/2012/09/objective-c-feature-availability-index/</link>
      <pubDate>Tue, 18 Sep 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/09/objective-c-feature-availability-index/</guid>
      <description>&lt;p&gt;Which modern Objective-C feature can you use where? Check the &lt;a href=&#34;http://developer.apple.com/library/ios/releasenotes/ObjectiveC/ObjCAvailabilityIndex/_index.html&#34;&gt;Objective-C Feature Availability Index&lt;/a&gt; (via &lt;a href=&#34;https://twitter.com/0xced/statuses/248017993903267841&#34;&gt;0xced&lt;/a&gt;).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Which modern Objective-C feature can you use where? Check the <a href="http://developer.apple.com/library/ios/releasenotes/ObjectiveC/ObjCAvailabilityIndex/_index.html">Objective-C Feature Availability Index</a> (via <a href="https://twitter.com/0xced/statuses/248017993903267841">0xced</a>).</p>
]]></content:encoded>
    </item>
    <item>
      <title>You don’t have to have 16:9 on day 1</title>
      <link>https://tewha.net/2012/09/you-dont-have-to-have-169-on-day-1/</link>
      <pubDate>Tue, 18 Sep 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/09/you-dont-have-to-have-169-on-day-1/</guid>
      <description>&lt;p&gt;You don’t have to build with armv7s &lt;a href=&#34;http://wanderingcoder.net/2012/09/16/no-armv7s-til-tested/&#34;&gt;right away&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And &lt;a href=&#34;http://daringfireball.net/linked/2012/09/18/netflix-iphone&#34;&gt;despite user demands&lt;/a&gt;, you also don’t have to support 16:9 right away either.&lt;/p&gt;
&lt;p&gt;It’s fine to get real hardware into your hands. More than fine; it’s being &lt;strong&gt;responsible&lt;/strong&gt;. Apple has you covered with letter boxing; let the 16:9 screen be their problem until you’re really ready to take full responsibility. By all means, do whatever development and simulator testing you want now. But wait for real hardware to ship.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>You don’t have to build with armv7s <a href="http://wanderingcoder.net/2012/09/16/no-armv7s-til-tested/">right away</a>.</p>
<p>And <a href="http://daringfireball.net/linked/2012/09/18/netflix-iphone">despite user demands</a>, you also don’t have to support 16:9 right away either.</p>
<p>It’s fine to get real hardware into your hands. More than fine; it’s being <strong>responsible</strong>. Apple has you covered with letter boxing; let the 16:9 screen be their problem until you’re really ready to take full responsibility. By all means, do whatever development and simulator testing you want now. But wait for real hardware to ship.</p>
<p>Always measure before cutting.</p>
<p>(But measure and cut quickly.)</p>
]]></content:encoded>
    </item>
    <item>
      <title>Do not release ARMv7s code until you have tested it</title>
      <link>https://tewha.net/2012/09/do-not-release-armv7s-code-until-you-have-tested-it/</link>
      <pubDate>Sun, 16 Sep 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/09/do-not-release-armv7s-code-until-you-have-tested-it/</guid>
      <description>&lt;p&gt;Apple defaults your projects to including ARMv7s code. But unless you can test it, &lt;a href=&#34;http://wanderingcoder.net/2012/09/16/no-armv7s-til-tested/&#34;&gt;turn it off&lt;/a&gt;. There’s nothing wrong with shipping ARMv7 code for a little while longer.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Apple defaults your projects to including ARMv7s code. But unless you can test it, <a href="http://wanderingcoder.net/2012/09/16/no-armv7s-til-tested/">turn it off</a>. There’s nothing wrong with shipping ARMv7 code for a little while longer.</p>
]]></content:encoded>
    </item>
    <item>
      <title>ADC incidents</title>
      <link>https://tewha.net/2012/09/adc-incidents/</link>
      <pubDate>Mon, 10 Sep 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/09/adc-incidents/</guid>
      <description>&lt;p&gt;In the past, I’ve tried to avoid using ADC incidents. You get two a year per program, and most years I’ve avoided using any. This year, I decided to use them both the iOS ones up before renewing.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In the past, I’ve tried to avoid using ADC incidents. You get two a year per program, and most years I’ve avoided using any. This year, I decided to use them both the iOS ones up before renewing.</p>
<p>The first one was clarification on how to fix a bug demonstrated by some Apple sample code. I got a response, but it wasn’t especially satisfying. But that’s okay, because in the end I found a way to do a different UI and avoid the bug entirely. Let’s call it a draw.</p>
<p>The second one, however, was a mistake in how I was using UIKit that I didn’t realize was a mistake. I boiled it down to a <a href="https://github.com/tewha/ExtraGridLines">test case</a> and submitted the project to Apple. As part of solving the incident, Apple not only explained what I was doing wrong, but provided snippets of code that would work.</p>
<p>This would be gold, but they also fully corrected my code the code I’d sent.</p>
<p>Of course, when I tried to integrate the solution back into my real application, I ran into other problems. However, the explanation Apple had offered me was enough that I was able to solve those other problems, too.</p>
<p>Basically, I got a fantastic code review out of that DTS incident by someone who clearly knows iOS and UIKit better than I ever will. Total win.</p>
<p>I don’t plan on wasting these in the future, but neither will I horde them in case of emergency. They’re worth using for the really nasty problems, and they’re not incredibly expensive to replace — $99 buys another two incidents.</p>]]></content:encoded>
    </item>
    <item>
      <title>Don’t write viewDidUnload</title>
      <link>https://tewha.net/2012/09/dont-write-viewdidunload/</link>
      <pubDate>Wed, 05 Sep 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/09/dont-write-viewdidunload/</guid>
      <description>&lt;p&gt;A lot of people misunderstand the point of &lt;code&gt;viewDidUnload&lt;/code&gt;. That’s because despite the name that implies otherwise, it is &lt;strong&gt;not&lt;/strong&gt; the counterpart of &lt;code&gt;viewDidLoad&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>A lot of people misunderstand the point of <code>viewDidUnload</code>. That’s because despite the name that implies otherwise, it is <strong>not</strong> the counterpart of <code>viewDidLoad</code>.</p>
<p>You should <strong>never</strong> consider a deallocation in <code>viewDidUnload</code> a proper balance for an allocation in <code>viewDidLoad</code>. In fact, you should probably shouldn’t write a <code>viewDidUnload</code>.</p>
<h2 id="make_your_outlets_unload_automatically">Make your outlets unload automatically</h2>
<p>The idea behind <code>viewDidUnload</code> is that the view is being unloaded out from behind your view controller. This gives you a chance to detach any pointers to it and clear any information you can rebuild easily. Your view will <em>probably</em> be loaded back in, at which point you’ll need to rebuild any caches. Apple describes this in <a href="http://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW36">UIViewController Class Reference</a>:</p>
<blockquote>
<p>When a low-memory condition occurs and the current view controller’s views are not needed, the system may opt to remove those views from memory. This method is called after the view controller’s view has been released and is your chance to perform any final cleanup. If your view controller stores separate references to the view or its subviews, you should use this method to release those references. You can also use this method to remove references to any objects that you created to support the view but that are no longer needed now that the view is gone. You should not use this method to release user data or any other information that cannot be easily recreated.</p>
</blockquote>
<p>This was mostly about handling <a href="http://en.wikipedia.org/wiki/Dangling_pointer">dangling pointers</a> before Automatic Reference Counting (ARC). But now that you’re <a href="%5B/2012/05/automatic-reference-counting/%5D">using ARC</a> and zeroing weak references, the dangling pointers will be cleaned up automatically. No need to write a <code>viewDidUnload</code>!</p>
<p>Generally, the stuff people put in <code>viewDidUnload</code> is better handled in <code>viewDidDisappear</code> or <code>dealloc</code>. The only thing left for <code>viewDidUnload</code> is nilling any of <strong>your</strong> caches that can be rebuilt without data loss while the view controller is still open, when needed at some point after the view has been reloaded. Really, these caches should be handled in <code>didReceiveMemoryWarning</code> instead.</p>
<h2 id="clearing_out_caches">Clearing out caches</h2>
<p>Clearing out cached information fits better into <code>didReceiveMemoryWarning</code>, so you should write it instead. Apple describes didReceiveMemoryWarning in <a href="http://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW4">UIViewController Class Reference</a>, too:</p>
<blockquote>
<p>You can override this method to release any additional memory used by your view controller. If you do, your implementation of this method must call the super implementation at some point to allow the view controller to release its view. If your view controller holds references to views in the view hierarchy, you should release those references in the <code>viewDidUnload</code> method instead.</p>
</blockquote>
<p>Not only does writing your cache purging in <code>didReceiveMemoryWarning</code> better suit the documentation, but you’ll be less confused when you read <code>didReceiveMemoryWarning</code> in your code than <code>viewDidUnload</code>.</p>
<p>I’m not taking a ridiculous position here, either. <code>viewDidUnload</code> is deprecated with iOS 6.</p>
<h2 id="summary">Summary</h2>
<ol>
<li>Use ARC.</li>
<li>Use weak references for <code>IBOutlets</code> that are part of the view hierarchy. They’ll automatically be zeroed when the view is unloaded.</li>
<li>Use <code>didReceiveMemoryWarning</code> to dispose of anything you can rebuild easily, by (for example) removing all objects from a <code>NSDictionary</code>. Or, better yet, use <code>NSCache</code> where this behaviour is automatic.</li>
<li>Use <code>dealloc</code> to dispose of any external resources that ARC will handle automatically.</li>
<li>Don’t even write a <code>viewDidUnload</code>, unless you’re observing values of outlets with KVO.</li>
</ol>
<p>If you’re still using Manual Release Retain, none of this applies. You should use retained outlets instead. It’s better to potentially use memory a little too long than to have a dangling pointer. And you should really think about climbing that fence and joining us on the Automatic Reference Counting side. Unbelievably, the grass is just as green here as it looks.</p>]]></content:encoded>
    </item>
    <item>
      <title>Modern Objective-C with iOS 5</title>
      <link>https://tewha.net/2012/08/modern-objective-c-with-ios-5/</link>
      <pubDate>Sat, 04 Aug 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/08/modern-objective-c-with-ios-5/</guid>
      <description>&lt;p&gt;Modern Objective-C contains subscripting support.&lt;/p&gt;
&lt;p&gt;Instead of writing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;NSString *value = [dict objectForKey: @&amp;quot;Key&amp;quot;];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can now write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;NSString *value = dict[@&amp;quot;Key&amp;quot;];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, this requires SDK support. While the OS X SDK provides this support, the iOS 5 SDK one doesn’t.&lt;/p&gt;
&lt;p&gt;I’m going to show you how to add it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Modern Objective-C contains subscripting support.</p>
<p>Instead of writing:</p>
<pre><code>NSString *value = [dict objectForKey: @&quot;Key&quot;];
</code></pre>
<p>You can now write:</p>
<pre><code>NSString *value = dict[@&quot;Key&quot;];
</code></pre>
<p>Unfortunately, this requires SDK support. While the OS X SDK provides this support, the iOS 5 SDK one doesn’t.</p>
<p>I’m going to show you how to add it.</p>
<h2 id="allow_subscripting_everywhere">Allow subscripting everywhere</h2>
<p>The iOS SDK provides routing from the new messages to the old via arclite, a library included automatically whenever you use Automatic Reference Counting. To add support for subscripts to Objective-C, you just need to inform the compiler it’s allowed to make those calls using a category.</p>
<p>Peter Steinberger explains and offers such a header in <a href="http://petersteinberger.com/blog/2012/using-subscripting-with-Xcode-4_4-and-iOS-4_3/">Using Subscripting With Xcode 4.4 and iOS 4.3+</a></p>
<p>You can <code>#import</code> this where needed, or add it to your precompiled header. There’s no need to add an implementation; it’s handled automatically by <code>arclite</code>. (If you are not using ARC, you will have to force the linker to include <code>arclite</code>. But you don’t have to actually switch to using ARC.)</p>
<p>I don’t recommend this, however. This will let you use subscript syntax with every type, not just those actually provided by the runtime. But if you use subscript syntax with a class that doesn’t support it, you’ll get a runtime error.</p>
<p>For instance, this will work:</p>
<pre><code>NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@&quot;foo&quot;] = @&quot;bar&quot;;
</code></pre>
<p>This, however, will build but cause a runtime error:</p>
<pre><code>NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSLog(@&quot;the value of key is %@&quot;, userDefaults[@&quot;key&quot;]);
</code></pre>
<p>We can do better.</p>
<h2 id="target_only_those_classes_supporting_subscripts">Target only those classes supporting subscripts</h2>
<p>We can also add subscripting support only on types you plan to use that you are certain arclite adds subscript support to.</p>
<p>Use a header like this:</p>
<pre><code>#if __IPHONE_OS_VERSION_MAX_ALLOWED &lt; 60000
@interface NSDictionary(subscripts)
- (id)objectForKeyedSubscript:(id)key;
@end

@interface NSMutableDictionary(subscripts)
- (void)setObject:(id)obj forKeyedSubscript:(id &lt;NSCopying&gt;)key;
@end

@interface NSArray(subscripts)
- (id)objectAtIndexedSubscript:(NSUInteger)idx;
@end

@interface NSMutableArray(subscripts)
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
@end
#endif
</code></pre>
<p>This will add subscripting support only to <code>NSArray</code> and <code>NSDictionary</code>. I don’t know what other classes Apple provides subscripting support for via arclite; if there’s a list, I haven’t found it yet.</p>
<p>I have put this code in a <a href="https://github.com/tewha/iOS-Subscripting">public github repository</a>; do with it as you will.</p>]]></content:encoded>
    </item>
    <item>
      <title>Keyboard type is not a validator</title>
      <link>https://tewha.net/2012/07/keyboard-type-is-not-a-validator/</link>
      <pubDate>Mon, 30 Jul 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/07/keyboard-type-is-not-a-validator/</guid>
      <description>&lt;p&gt;So you’ve set your &lt;code&gt;UITextField&lt;/code&gt;’s &lt;code&gt;keyboardType&lt;/code&gt; to only accept numbers. Or email addresses, or URLs, or whatever. Fine. You’re done, right?&lt;/p&gt;
&lt;p&gt;What are you going to do if they enter something else in there?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UITextField&lt;/code&gt;’s keyboard type is a &lt;em&gt;keyboard type&lt;/em&gt;, not a validator.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>So you’ve set your <code>UITextField</code>’s <code>keyboardType</code> to only accept numbers. Or email addresses, or URLs, or whatever. Fine. You’re done, right?</p>
<p>What are you going to do if they enter something else in there?</p>
<p><code>UITextField</code>’s keyboard type is a <em>keyboard type</em>, not a validator.</p>
<p>Here’s two examples:</p>
<h2 id="emoji">Emoji</h2>
<ol>
<li>Edit a contact in Contacts.</li>
<li>Tap a name field.</li>
<li>Switch to the Emoji keyboard.</li>
<li>Tap the phone number field.</li>
</ol>
<p>Contacts will stop you from actually putting Emoji into the phone number field, but this is a feature of <strong>Contacts</strong> not of <code>UITextField</code>. If you try this in your own app, you’ll be able to enter Emoji there.</p>
<h2 id="paste">Paste</h2>
<ol>
<li>Edit a contact in <strong>Contacts</strong>.</li>
<li>Tap a name field.</li>
<li>Tap and hold.</li>
<li>Select some text.</li>
<li>Tap <strong>Copy</strong>.</li>
<li>Tap the phone number field.</li>
<li>Tap and hold.</li>
<li>Tap <strong>Paste</strong>.</li>
</ol>
<h2 id="so_what_do_you_do">So what do you do?</h2>
<p>Now that you’ve started thinking about this, I bet you can find other ways to reproduce this.</p>
<p>This is not your bug. It’s probably not a bug at all. But you need to adjust your expectations appropriately.</p>
<p>You could probably trap <code>textField:shouldChangeCharactersInRange:replacementString:</code> like Contacts does. This may be doing more work than necessary.</p>
<p>However, you <strong>absolutely</strong> should test your code to see how it handles bendy inputs. If it crashes, you really should make your code more paranoid about its inputs. Whoever’s bug it is, it’s not a good excuse to crash.</p>]]></content:encoded>
    </item>
    <item>
      <title>Wireless proxies may re-compress your files</title>
      <link>https://tewha.net/2012/06/wireless-proxies-may-re-compress-your-files/</link>
      <pubDate>Thu, 07 Jun 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/06/wireless-proxies-may-re-compress-your-files/</guid>
      <description>&lt;p&gt;If you’re downloading a file with widely-recognized lossy compression, your user’s cellular provider may interfere with it. This has always been true of internet connections; I first ran into this with dialup years ago. But it went away for a while with broadband, is back with wireless.&lt;/p&gt;
&lt;p&gt;The simplest example is a JPEG. You may get the JPEG you expect, but it’s also possible for the proxy to deliver a smaller JPEG than you expect. The cell provider considers it “close enough”, and the doubly-compressed JPEG is smaller (and far uglier).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>If you’re downloading a file with widely-recognized lossy compression, your user’s cellular provider may interfere with it. This has always been true of internet connections; I first ran into this with dialup years ago. But it went away for a while with broadband, is back with wireless.</p>
<p>The simplest example is a JPEG. You may get the JPEG you expect, but it’s also possible for the proxy to deliver a smaller JPEG than you expect. The cell provider considers it “close enough”, and the doubly-compressed JPEG is smaller (and far uglier).</p>
<p>This may be true of other file types as well, if they’re commonly recognized as lossy and computationally easy to re-compress.</p>
<p>I have read reports of T-Mobile and O2 doing this. I think it’s been noted with other cell providers, too.</p>
<p>There’s two possible fixes:</p>
<ul>
<li>Switching to HTTPS will fix this problem as the proxy will no longer be in the middle of the communication. If your resource is available via HTTPS, this is a fantastic and simple fix.</li>
<li>Add a HTTP header to defeat this. The idea is to add a no-transform cache-control HTTP header to your request. This should disallow the server from making this kind of change. See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5">RFC 2616, section 14.9.5</a>.</li>
</ul>
<p><em>Thanks to <a href="http://www.tonymillion.com">Tony Milllion</a> for pointing out the HTTPS solution, and letting me know it affected O2 as well.</em></p>]]></content:encoded>
    </item>
    <item>
      <title>AFNetworking: a well managed open source project</title>
      <link>https://tewha.net/2012/06/afnetworking-a-well-managed-open-source-project/</link>
      <pubDate>Wed, 06 Jun 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/06/afnetworking-a-well-managed-open-source-project/</guid>
      <description>&lt;p&gt;Last week, I talked about &lt;a href=&#34;https://tewha.net/2012/06/networking-using-nsurlconnection&#34;&gt;Networking using NSURLConnection&lt;/a&gt;. In a future post, I’m going to talk about how to use AFNetworking. But first, I wanted to talk about why you should trust AFNetworking as a project in your project.&lt;/p&gt;
&lt;p&gt;I haven’t been using github for long. That said, AFNetworking is the best-managed git project I’ve seen. It’s being managed so well that I wanted to write about it. In doing so, I’m not trying to praise Mattt Thompson’s efforts. It will probably come across that way, and he deserves it. Instead, I want to say that if you plan to maintain a git project, you should handle it as well as Mattt does.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Last week, I talked about <a href="/2012/06/networking-using-nsurlconnection">Networking using NSURLConnection</a>. In a future post, I’m going to talk about how to use AFNetworking. But first, I wanted to talk about why you should trust AFNetworking as a project in your project.</p>
<p>I haven’t been using github for long. That said, AFNetworking is the best-managed git project I’ve seen. It’s being managed so well that I wanted to write about it. In doing so, I’m not trying to praise Mattt Thompson’s efforts. It will probably come across that way, and he deserves it. Instead, I want to say that if you plan to maintain a git project, you should handle it as well as Mattt does.</p>
<h2 id="codebase">Codebase</h2>
<p>AFNetworking is, ultimately, a simple library. It has only a few classes, and reuses lots of the sane bits of iOS frameworks. Its main class is <code>AFURLConnectionOperation</code>, which encapsulates a <code>NSURLConnection</code> and its delegate methods in a subclass of <code>NSOperation</code>.</p>
<p>Without going into the gory details of Foundation framework classes, this is how iOS networking <strong>should</strong> work. Of course, you could get into a lot of trouble even with the right fundamentals. But AFNetworking doesn’t. It’s ten source files with headers, and one header to rope it all together.</p>
<h2 id="issues">Issues</h2>
<p>As I write this, AFNetworking has 368 closed issues. 358 of them are closed. Alone, this tells you something: He responds to issues.</p>
<p>But if you watch how he handles issues, you’ll see qualities to which all developers should aspire:</p>
<ol>
<li>Patience.</li>
<li>Humility.</li>
</ol>
<p>His responses are available to everyone, of course. I came to appreciate how well Mattt was running the project by reading these. Along the way, I learned a lot about AFNetworking.</p>
<h2 id="pull_requests">Pull requests</h2>
<p>I have no idea what percentage of the code Mattt has written, vs. code brought in by other contributors. I can tell you that at the moment, AFNetworking has 99 pull requests total. 98 of these are closed. Whether they were merged or not, he’s dealt with them.</p>
<p>Some of these pull requests are pretty mundane. I’ve landed three myself, all very small and ordinary. However, in each case Mattt not only merged the request, but thanked me for it and explained what had happened. The thanks are appreciated. The explanation isn’t necessary, but gives me a better feeling of connectedness.</p>
<p>For the pull request that he <strong>didn’t</strong> accept, he explained what I was doing wrong (gently and politely), and provided me with an alternative that actually worked better than the pull request I’d made.</p>
<p>Looking through a few pull requests, I don’t see anything unusual about the way he treated me.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Look, I’m not saying Mattt Thompson is handling AFNetworking perfectly. That’d be impossible to prove, and you could probably prove otherwise pretty quickly. But he’s handling it <strong>well</strong>.</p>
<p>I’m also not going to claim the code is perfect. The library actually swizzles itself, which is one of the craziest things I’ve seen. But the craziness is localized to a small section of code, and minor overall.</p>
<p>I’m feeling connected to the project, I’m feeling confident, and I’m learning more about it. Even the bits I don’t care about yet. And if that isn’t a successful open source project, I’m not sure what is.</p>]]></content:encoded>
    </item>
    <item>
      <title>Using blocks to handle errors</title>
      <link>https://tewha.net/2012/06/using-blocks-to-handle-errors/</link>
      <pubDate>Tue, 05 Jun 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/06/using-blocks-to-handle-errors/</guid>
      <description>&lt;p&gt;In the past, I’ve talked about &lt;a href=&#34;https://tewha.net/2011/07/blocks-to-remove-redundancy/&#34;&gt;Using blocks to remove redundancy&lt;/a&gt;. But now I want to explain the pattern I’ve adopted since, which is my favorite block pattern of all. Even though it, too, is all about removing redundancy: handling errors.&lt;/p&gt;
&lt;p&gt;Although Objective-C supports exceptions, they’re not commonly used. A thrown exception is usually not caught, making it a fatal error.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In the past, I’ve talked about <a href="/2011/07/blocks-to-remove-redundancy/">Using blocks to remove redundancy</a>. But now I want to explain the pattern I’ve adopted since, which is my favorite block pattern of all. Even though it, too, is all about removing redundancy: handling errors.</p>
<p>Although Objective-C supports exceptions, they’re not commonly used. A thrown exception is usually not caught, making it a fatal error.</p>
<p><a href="https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocExceptionHandling.html#//apple_ref/doc/uid/TP30001163-CH13-TPXREF168">The Objective-C Programming Language</a> describes it thus:</p>
<blockquote>
<p><strong>Important</strong> In many environments, use of exceptions is fairly commonplace. For example, you might throw an exception to signal that a routine could not execute normally—such as when a file is missing or data could not be parsed correctly. Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors. Instead you should use the return value of a method or function to indicate that an error has occurred, and provide information about the problem in an error object. For more information, see <a href="http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/ErrorHandling.html#//apple_ref/doc/uid/TP40001806">Error Handling Programming Guide</a>.</p>
</blockquote>
<p>What, then, is the usual pattern for handling non-fatal errors. The answer is the <code>NSError class</code>, along with a few simple conventions:</p>
<ol>
<li>Any method that can fail should return 0 (or an equivalent) on failure.</li>
<li>Any method that fails by returning 0 (or an equivalent) on failure should take a pointer to return a <code>NSError</code> instance, which it populates with error details.</li>
<li>If the error pointer is <code>NULL</code>, the method should not return an error.</li>
</ol>
<p>For instance:</p>
<pre><code>- (BOOL)doSomethingWithError: (NSError **)error {

    // other code
    NSError *e;
    if ( ![self bitWithError: &amp;e] ) {
        if (error) *error = e;
        return NO;
    }
    
    return YES;
}
</code></pre>
<p>This seems pretty reasonable, but can get unmanageable quickly:</p>
<pre><code>- (BOOL)doSomethingWithError: (NSError **)error {
    
    NSError *e;
    
    if ( ![self part1WithError: &amp;e] ) {
        if (error) *error = e;
        return NO;
    }
    
    if ( ![self part2WithError: &amp;e] ) {
        if (error) *error = e;
        return NO;
    }
    
    if ( ![self part3WithError: &amp;e] ) {
        if (error) *error = e;
        return NO;
    }
    
    return YES;
}
</code></pre>
<p>Thankfully, blocks can simplify this for us!</p>
<pre><code>- (BOOL)doSomethingWithError: (NSError **)error {

    BOOL(^fail)(NSError *e) = ^(NSError *e) {
        if (error) *error = e;
        return NO;
    };
    
    NSError *e;
    if ( ![self part1WithError: &amp;e] ) return fail(e);
    
    if ( ![self part2WithError: &amp;e] ) return fail(e);
    
    if ( ![self part3WithError: &amp;e] ) return fail(e);
    
    return YES;
}
</code></pre>
<p>Using a fail block has a few advantages:</p>
<ul>
<li>You have a single place through which all errors in this method are routed. You can put a breakpoint here, or add logging.</li>
<li>If you change what doSomethingWithError returns, you change just the return type of the block and the return within the block.</li>
<li>You eliminate a lot of redundant code, therefore lessening the chance of an error in one of the copies.</li>
</ul>
<p>Footnote: Usually, if I am writing an if statement, I’ll write it like this:</p>
<pre><code>if (foo) {
    // statement
}
</code></pre>
<p>I do this even when it’s not necessary, because what if I expand on it later? And I think this is a good principle. But for a fail block like this, I’m <em>never</em> going to add an extra statement. The whole point of the block is to make sure that the failure code is a single statement.</p>]]></content:encoded>
    </item>
    <item>
      <title>Networking using NSURLConnection</title>
      <link>https://tewha.net/2012/06/networking-using-nsurlconnection/</link>
      <pubDate>Mon, 04 Jun 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/06/networking-using-nsurlconnection/</guid>
      <description>&lt;p&gt;In a previous article, I mentioned how to &lt;a href=&#34;handling-302303-redirects&#34;&gt;handle 302/303 redirects to web services&lt;/a&gt;. But that’s a fairly advanced topic, and we should have built up to that.&lt;/p&gt;
&lt;p&gt;What I’m going to cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The basics of networking using &lt;code&gt;NSURLConnection&lt;/code&gt;, part of Apple’s Foundation framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I’m not going to cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to determine if a connection is available before trying a request. (Hint: Don’t.)&lt;/li&gt;
&lt;li&gt;How to retry an operation when a connection becomes available. (Hint: Reachability.)&lt;/li&gt;
&lt;li&gt;How to abstract this without losing anything important, and bring it all under control. (Hint: Use &lt;a href=&#34;https://github.com/AFNetworking/AFNetworking/&#34;&gt;AFNetworking&lt;/a&gt;.)&lt;/li&gt;
&lt;/ul&gt;</description>
      <content:encoded><![CDATA[<p>In a previous article, I mentioned how to <a href="handling-302303-redirects">handle 302/303 redirects to web services</a>. But that’s a fairly advanced topic, and we should have built up to that.</p>
<p>What I’m going to cover:</p>
<ul>
<li>The basics of networking using <code>NSURLConnection</code>, part of Apple’s Foundation framework.</li>
</ul>
<p>What I’m not going to cover:</p>
<ul>
<li>How to determine if a connection is available before trying a request. (Hint: Don’t.)</li>
<li>How to retry an operation when a connection becomes available. (Hint: Reachability.)</li>
<li>How to abstract this without losing anything important, and bring it all under control. (Hint: Use <a href="https://github.com/AFNetworking/AFNetworking/">AFNetworking</a>.)</li>
</ul>
<p>All of these are topics I’ll write about in future articles. But today, just the basics!</p>
<p>Also, this code will assuming you’re using Automatic Reference Counting. Because <a href="/2012/05/automatic-reference-counting/">you ought to be</a>.</p>
<p>For any HTTP operation, you’re going to use <code>NSURLConnection</code>. It’s not safe to use synchronously from the main thread. This will cause the main thread to stop responding to user-level events, and iOS will quit your application. It behaves exactly as if your application crashed.</p>
<p>On Mac OS X, the system will not quit your application, though your application will become unresponsive and <strong>look</strong> like it’s frozen. So on Mac OS X, you should follow the same pattern of avoiding synchronous network requests on the main thread of your application.</p>
<p>That leaves three options:</p>
<ol>
<li>Asynchronous networking on the main thread.</li>
<li>Synchronous networking on another thread.</li>
<li>Asynchronous networking on another thread.</li>
</ol>
<p>Under normal circumstances, you don’t need to run networking operations on a different thread. There’s very few problems that require moving to another thread.</p>
<p>Using asynchronous operation will cause the networking itself to run in the background. You can consider this a dedicated thread by Apple. Your delegate methods will be called in the correct sequence on the main thread to catch up with networking as iOS determines it is appropriate.</p>
<p>Apple includes an example of how to use <code>NSURLConnection</code> in <a href="https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html">URL Loading System Programming Guide, Using NSURLConnection</a>. It’s a short article, full of simple code examples. You should spend a few minutes to read this.</p>
<p>In a nutshell, here’s the pattern:</p>
<ol>
<li>Keep a <code>NSMutableData</code> for your response data.</li>
<li>Clear the contents <code>NSMutableData</code> instance in <code>connection:didReceiveResponse:</code>. (You may receive multiple <code>connection:didReceiveResponse:</code> events as the request is redirected, but you should only use data from the last one.)</li>
<li>Append the data you receive from didReceiveData to the <code>NSMutableData</code>. Don’t try to process it immediately; you will usually receive multiple <code>connection:didReceiveData:</code> events for a single transfer.</li>
<li>In <code>connectionDidFinishLoading:</code>, your data is complete. Here, you can do something with it.</li>
</ol>
<p>The idea here is that your start (or restart) accumulating data in <code>connection:didReceiveResponse:</code>, append data in your <code>connection:didReceiveData:</code>, and actually do something with the data in <code>connection:connectionDidFinishLoading:</code>.</p>
<p>Processing the data shouldn’t really be done on the main thread, either. You can start another thread, but it’s easier to just <code>dispatch_async</code> to a queue that isn’t running on the main thread.</p>
<p>It is possible to run an <code>NSURLConnection</code> on another thread, of course. That thread will need to be using a run loop to receive the delegate events from networking. But unless there’s some reason you need a separate thread, using asynchronous networking is Apple’s solution to this.</p>
<p>Using <code>NSURLConnection</code> requires a class member to accumulate data as its transferred. That means that if you’re going to have multiple simultaneous transfers, you’ll need something more complicated. Probably a wrapper class to drive <code>NSURLConnection</code>, and keep each response separate. By the time you’ve written this wrapper class, you’ve probably written a naive version of <code>AFHTTPRequestOperation</code>, a part of AFNetworking.</p>
<p>But we’ll get to AFNetworking in a future post.</p>
<p>Assuming you only have a single transfer going on at once, your code should look a bit like this:</p>
<pre><code>- (void)doNetworkThing {

    NSURL *URL = [NSURL URLWithString: @&quot;http://tewha.net/&quot;];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL: URL];
    NSURLConnection *connection = [[NSURLConnection alloc]
                                   initWithURLRequest: request];

    receivedData = [[NSMutableData alloc] init]; // should be a class member
    [connection start];
}

- (void)connection:(NSURLConnection *)connection
didReceiveResponse:(NSURLResponse *)response {
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection
    didReceiveData:(NSData *)data {
    [receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error {
    // do something with error here
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    dispatch_async(someQueue, ^{
        // do something that takes a long time with receivedData here
        dispatch_async( dispatch_get_main_queue(), ^{
            // access the UI here
        });
    });
}
</code></pre>
<p>See also:</p>
<ul>
<li><a href="https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html">URL Loading System Programming Guide, Using NSURLConnection</a></li>
<li><a href="https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html">NSURLConnection Class Reference</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Don’t write new apps that target iOS 4</title>
      <link>https://tewha.net/2012/06/dont-write-new-apps-that-target-ios-4/</link>
      <pubDate>Fri, 01 Jun 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/06/dont-write-new-apps-that-target-ios-4/</guid>
      <description>&lt;p&gt;So you’re writing your first iPhone app. Welcome! But which version of iOS should you target?&lt;/p&gt;
&lt;p&gt;This is pretty simple. There’s very little reason not to write for iOS 5.0.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>So you’re writing your first iPhone app. Welcome! But which version of iOS should you target?</p>
<p>This is pretty simple. There’s very little reason not to write for iOS 5.0.</p>
<h2 id="market_share">Market share</h2>
<p>According to <a href="http://www.game4mob.com/index.php/tech-articles/67-ios-5-penetration-percentage">iOS 5 penetration percentage</a>, iOS 5 has more than 80% of the market at this point. This is only covering one developer’s apps, but it’s cool nonetheless because the data is updated daily.</p>
<p>A bigger sample has been analyzed in <a href="http://pxldot.com/post/18754186750/ios-ebb-and-flow">iOS Ebb and Flow</a>. This article says that across multiple developers’ apps iOS 5 had captured 76% of all iOS users by March 1, 2012.</p>
<h2 id="technology">Technology</h2>
<p>As big a release as iOS 5 was for users, it was even bigger for developers. You’re going to want to use some of Apple’s new technologies.</p>
<p>If you try to target anything older, there’s a couple major features you’ll be unable to use <em>at all</em>:</p>
<ul>
<li><strong>Automatic Reference Counting with weak references.</strong> Instead of writing memory management code, you describe the relationship between objects and the compiler writes the memory management code for you. On iOS 4, you can get Automatic Reference Counting without support for weak references. But ARC and weak references are a <strong>huge</strong> deal; see <a href="/2012/05/automatic-reference-counting/">Automatic Reference Counting</a> for more.</li>
<li><strong>Storyboards.</strong> Storyboards aren’t available on iOS 4. Storyboards mean that instead of creating each screen’s layout in its xib and writing code to connect them, you define a single storyboard defines all your screens and even strings them together. You’ll still need to write code, of course, but the code will be less concerned with the minutiae of transitioning between screens.</li>
</ul>
<p>There’s several more features you can take advantage of iOS 5. Unlike the above list, you can build these into an iOS 4 project, but you’ll need to be careful not to try to use them on iOS 4:</p>
<ul>
<li>iCloud</li>
<li>Twitter integration</li>
<li>Notification center</li>
<li>Enhanced AirPlay</li>
<li>Enhanced Core Image</li>
</ul>
<h2 id="hardware">Hardware</h2>
<p>You’ll have a much harder time finding devices to test on. It isn’t enough to target iOS 4, test on iOS 5, and declare it’ll work on iOS 4. It probably won’t without some fixes.</p>
<p>Remember, also, that iPhones cannot be downgraded to a previous version of iOS. If it ships with iOS 5 or you ever accidentally update it, it’s an iOS 5-only device.</p>
<p>But what about hardware support? Who can’t run iOS 5?</p>
<p>Well, every iPhone since the 3GS can be upgraded to iOS 5. The newest iPhone that can’t run iOS 5 was discontinued in June 2010. Apple hasn’t released a software update to it since November 2010. It not only doesn’t run iOS 5, but doesn’t run the latest version of iOS 4. Even if a person bought that phone on its last days on a two year contract, that contract will be up before you finish your app.</p>
<p>Finally, you’ll get to skip supporting the armv6 CPU architecture. Apple’s had some significant armv6 code generation bugs. While at the moment they’re still trying, how long will they continue to try?</p>
<p>Apple doesn’t ship armv6 devices anymore, and the effort to keep the armv6 code generation working seems significant. Each time they slip up, someone gets embarrassed. I can’t imagine they’ll continue to support armv6 code generation for long.</p>
<h2 id="over_the_air">Over The Air</h2>
<p>Now that I’ve convinced you to target iOS 5, let me suggest you target only the latest version of iOS, currently 5.1.1. The comments above about not being to downgrade a device from iOS 5 to iOS 4 also apply on downgrading from iOS 5.1.1 to iOS 5.0.</p>
<p>I think you’d probably be on much more solid ground developing for 5.1.1 and allowing operation on 5.0, but if you ever find a bug that occurs only on iOS 5.0 you’re probably not going to be able to recreate it.</p>
<p>Meanwhile, updating from iOS 5.0 to 5.1.1 is just a simple, small over the air update away, and is supported by every device running iOS 5.0. It turns out that <a href="http://david-smith.org/blog/2012/05/11/ios-5-dot-1-1-upgrade-stats/index.html">users upgrade fast</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>If you try to support iOS 4 you are giving up a lot of OS features, and going against the grain of Apple’s tool development, just to chase an ever-shrinking (in both real and percentage terms) market of users who are less likely to be interested in new software.</p>
<p>Are you <em>nuts</em>?</p>]]></content:encoded>
    </item>
    <item>
      <title>Automatic Reference Counting</title>
      <link>https://tewha.net/2012/05/automatic-reference-counting/</link>
      <pubDate>Thu, 31 May 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/05/automatic-reference-counting/</guid>
      <description>&lt;p&gt;If you’re an application developer: Yes, you should use Automatic Reference Counting (ARC).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>If you’re an application developer: Yes, you should use Automatic Reference Counting (ARC).</p>
<p>Odds are, the compiler understands Objective-C and Cocoa better than you. I don’t mean this as an insult; it certainly understands it better than me. I think you could safely say it understands the rules better than all but maybe a dozen people worldwide. And it knows tricks to use them to a degree that you and I can’t repeat, even if we understood as well as it does.</p>
<p>The rest is just details, but they’re important:</p>
<ol>
<li>You will write a lot less boring code. Code so boring it’s easy to make mistakes.</li>
<li>As a blended compile time and run time process, it has access to tricks that you don’t.</li>
<li>It will a better a job of writing memory management code than you can, even if you write the theoretical perfect memory management code.</li>
<li>It will reduce “high tide” memory usage (somewhat) without any effort on your part.</li>
</ol>
<p>If you are starting a new application, stop thinking about it and just use it.</p>
<p>If you have an existing application, you need to think about it. You’re balancing the ease of future development vs. a need to re-test the app. The ARC conversion isn’t awful, but it isn’t painless or foolproof either. You will need to make sure you have no circular references, and you will need to make sure that objects don’t disappear sooner than you think.</p>
<p>If you have an existing application that targets iOS before iOS 5, zeroing weak references are not supported. You can find people who will tell you that zeroing weak references aren’t a big deal. They’re wrong. While it’s true you can use assign to prevent circular references, weak references are what turns ARC from a useful way to write less code to a fantastic way to write stable applications. You should seriously consider requiring iOS 5.</p>
<p>If you have an existing application that targets iOS before iOS 4, you can’t use it at all. What are you thinking, supporting a version of iOS that old?</p>
<p>See also:</p>
<ul>
<li><a href="https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226">Transitioning to ARC</a>: Apple’s ARC overview. A great overview, but possibly less than you need to know.</li>
<li><a href="http://clang.llvm.org/docs/AutomaticReferenceCounting.html">Automatic Reference Counting</a>: The living and detailed ARC specification and rationales. Certainly much more information than you require.</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Handling 302/303 redirects</title>
      <link>https://tewha.net/2012/05/handling-302303-redirects/</link>
      <pubDate>Wed, 30 May 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/05/handling-302303-redirects/</guid>
      <description>&lt;p&gt;If you try to POST to a web API using &lt;code&gt;NSURLConnection&lt;/code&gt; that redirects you using a &lt;a href=&#34;http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.3&#34;&gt;302&lt;/a&gt; or &lt;a href=&#34;http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4&#34;&gt;303&lt;/a&gt; redirect, you’ll fall over to a GET request. This is intentional, but you can override it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>If you try to POST to a web API using <code>NSURLConnection</code> that redirects you using a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.3">302</a> or <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4">303</a> redirect, you’ll fall over to a GET request. This is intentional, but you can override it.</p>
<p>With HTTP status codes 302 and 303, the user agent (in this case, <code>NSURLConnection</code>) will change the request type from POST to GET. This is just how 302 was usually implemented; status code 303 was added to HTTP/1.1 to make this behaviour explicit.</p>
<p>HTTP/1.1 also added a status code to redirect without changing the request type from POST to GET. If you can change the web site, getting it to redirect you with a <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.8">307</a> instead will fix the problem.</p>
<p>If not, you can make <code>NSURLRequest</code> ignore this aspect of RFC2616.</p>
<p><code>NSURLRequest</code> sends an event to its delegate, in which you can see what <code>NSURLRequest</code> plans to do and customize it:</p>
<pre><code>- (NSURLRequest *)connection: (NSURLConnection *)connection
             willSendRequest: (NSURLRequest *)request
            redirectResponse: (NSURLResponse *)redirectResponse;
{
    if (redirectResponse) {
        NSMutableURLRequest *r = [[originalRequest mutableCopy] autorelease];
        [r setURL: [request URL]];
        return r;
    } else {
        return request;
    }
}
</code></pre>
<p>By doing this, you’re cloning the original request and changing the URL to match the request suggested by <code>NSURLConnection</code> (which is following the RFC).</p>
<p>See also:</p>
<ul>
<li>w3.org: <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">RFC2616 HTTP/1.1, section 10: Status Code Definitions</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Objective-C memory management</title>
      <link>https://tewha.net/2011/08/objective-c-memory-management/</link>
      <pubDate>Sun, 21 Aug 2011 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2011/08/objective-c-memory-management/</guid>
      <description>&lt;p&gt;With Automatic Reference Counting (ARC) coming out soon, you could argue this post is coming almost too late. But there’s a lot of confusion over this, and I don’t think ARC will help much if you don’t understand the &lt;em&gt;why&lt;/em&gt; of memory management.&lt;/p&gt;
&lt;p&gt;After a couple years, I’ve come to adopt some very simple rules for memory management.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>With Automatic Reference Counting (ARC) coming out soon, you could argue this post is coming almost too late. But there’s a lot of confusion over this, and I don’t think ARC will help much if you don’t understand the <em>why</em> of memory management.</p>
<p>After a couple years, I’ve come to adopt some very simple rules for memory management.</p>
<h2 id="concepts">Concepts</h2>
<p>The first step is to pick up a few concepts that will help you as you code.</p>
<ul>
<li><strong>Be lazy in memory management.</strong> Rely on the compiler to do everything it possibly can. The compiler can synthesize property setters that handle memory management according to the rules you set. Rely on this.</li>
<li><strong>Ownership.</strong> Think in terms of ownership, rather than reference counting. Thinking in terms of ownership makes problems and solutions obvious. Thinking in terms of ownership will help you keep in mind the <em>why</em> of what you’re doing, rather than the <em>what</em>. After you’ve got a good grasp of <em>why</em>, the <em>what</em> becomes obvious.</li>
<li><strong>Protect your objects.</strong> Own any object that you want to keep around as long as <code>self</code> is around.</li>
<li><strong>Avoid circular references.</strong> Never own an object that could own <code>self</code>. This means never owning <code>self</code>’s delegate or data source.</li>
</ul>
<h2 id="practical_guidelines">Practical guidelines</h2>
<p>But how does this translate to code? There’s a few specific and concrete things you can do to make this easier on yourself:</p>
<ul>
<li><strong>Use properties to centralize memory management rules.</strong> Use <code>@property</code> to establish the rules for memory management of an instance variable. (And <code>@synthesize</code> your properties to underscored instance variables to prevent naming conflicts.)</li>
<li><strong>Pick the right memory management rule.</strong> Use <code>retain</code> properties as your default. Data sources, delegates or other objects that might own the object you’re working in should be <code>assign</code> properties instead of <code>retain</code>.</li>
<li><strong>Rely on the centralized memory management rules.</strong> Use property set notation (<code>self.foo = nil;</code>) or the property setter (<code>[self setFoo: nil];</code>) everywhere you change the property’s value except in the property’s setter (if you need one) In this way, you rely on the <code>retain</code> or <code>assign</code> in your <code>@property</code> to specify the memory management. If you need to use <code>retain</code>, <code>release</code> or <code>autorelease</code> outside of a setter you’re doing too much. (And, also, you’ll have more work to do to be compatible with ARC.)</li>
<li><strong>Avoid being called once deallocated.</strong> In <code>dealloc</code>, <code>nil</code> any delegates you’ve set to <code>self</code>. (This eliminates the possibility that the object will survive longer than <code>self</code> and try to send messages to <code>self</code>.)</li>
<li><strong>Protect your private bits, too.</strong> Don’t use raw instance variables in objects requiring memory management. Use anonymous properties.</li>
<li><strong>Containers own their contents.</strong> You not only don’t need to but must not try to manage memory in a system container. An <code>NSArray</code> will send a <code>retain</code> to objects that are added to it, and a <code>release</code> to objects as they are removed. If you try to manually <code>retain</code> and <code>release</code> objects, you’ll miss a case.</li>
<li><strong>Verify.</strong> Analyze your code frequently. And profile your code early and often for leaks.</li>
</ul>]]></content:encoded>
    </item>
  </channel>
</rss>
