<?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/</link>
    <description>Recent content on Tewha.net</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 15 Sep 2025 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://tewha.net/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>macOS Tahoe Impressions</title>
      <link>https://tewha.net/2025/09/macos-tahoe-impressions/</link>
      <pubDate>Wed, 17 Sep 2025 19:21:23 +0000</pubDate>
      <guid>https://tewha.net/2025/09/macos-tahoe-impressions/</guid>
      <description>&lt;p&gt;Let&amp;rsquo;s start with the things I like.&lt;/p&gt;
&lt;p&gt;My favourite Tahoe features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Group chats now sport animated backgrounds. Yes, it&amp;rsquo;s a small touch that can make Messages feel livelier… but more importantly, I hope to never send a group a message that I meant for an individual again.&lt;/li&gt;
&lt;li&gt;Safari&amp;rsquo;s reader mode automatically summarizes the article you&amp;rsquo;re reading in the right rail, sometimes giving you the article headings.&lt;/li&gt;
&lt;li&gt;Control centre and menu bar extras got another pass. It&amp;rsquo;s an improvement.&lt;/li&gt;
&lt;li&gt;Spotlight&amp;rsquo;s new UI now has a dedicated app search, which I&amp;rsquo;ll use a lot. Spotlight also gains a clipboard history, which I hope I remember to use. But probably not.&lt;/li&gt;
&lt;li&gt;Apple’s Journal app makes its macOS debut for those who like to capture daily reflections.&lt;/li&gt;
&lt;li&gt;I feel that Xcode 26 is a big improvement in many little ways, although I didn&amp;rsquo;t do much Mac development during Sequoia&amp;rsquo;s tenure. I may be appreciating two years of changes here! The AI assistant is great at offering code changes, though you need to watch what you ask it and watch it &lt;em&gt;really&lt;/em&gt; carefully.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not everything is great, though.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Let&rsquo;s start with the things I like.</p>
<p>My favourite Tahoe features:</p>
<ul>
<li>Group chats now sport animated backgrounds. Yes, it&rsquo;s a small touch that can make Messages feel livelier… but more importantly, I hope to never send a group a message that I meant for an individual again.</li>
<li>Safari&rsquo;s reader mode automatically summarizes the article you&rsquo;re reading in the right rail, sometimes giving you the article headings.</li>
<li>Control centre and menu bar extras got another pass. It&rsquo;s an improvement.</li>
<li>Spotlight&rsquo;s new UI now has a dedicated app search, which I&rsquo;ll use a lot. Spotlight also gains a clipboard history, which I hope I remember to use. But probably not.</li>
<li>Apple’s Journal app makes its macOS debut for those who like to capture daily reflections.</li>
<li>I feel that Xcode 26 is a big improvement in many little ways, although I didn&rsquo;t do much Mac development during Sequoia&rsquo;s tenure. I may be appreciating two years of changes here! The AI assistant is great at offering code changes, though you need to watch what you ask it and watch it <em>really</em> carefully.</li>
</ul>
<p>Not everything is great, though.</p>
<ul>
<li>The new volume and brightness HUDs are easy to miss, and I expect to overlook them entirely most of the time</li>
<li>Some of Apple’s own apps still do menu bar extras the old way.</li>
<li>While Spotlight is improved, I had to force it to re-index—a maintenance chore that should be automatic.</li>
</ul>
<p>I want to mention Launchpad here. Personally, I just use Spotlight. But others seem to be really missing it.</p>
<p>Then there’s the downright ugly.</p>
<ul>
<li>Most of the interface looks muddled unless you turn on “Reduce Transparency,” which defeats the point of Tahoe’s glossy new design.</li>
<li>Off by one (and more) errors abound in the UI.</li>
<li>The so-called Icon Jail just adds unnecessary ugliness.</li>
<li>The menu bar intentionally vanishes into invisibility.</li>
<li>The alert popups look like they were designed by two different people who didn&rsquo;t talk. The text is left aligned, which is fine. The icon is also left aligned, which is also fine. But the icon sits above the text, giving it a horrible look overall.</li>
</ul>
<p>I&rsquo;m going to continue to use Tahoe, because I like Xcode 26. And oddly, I trust macOS 26 with my data. In the past, it&rsquo;s felt sometimes like Apple has half executed on a plan and missed as a result. Here, it feels like they locked in their plan early and made very few changes during Tahoe&rsquo;s development. It was just an ugly and inconsistent design.</p>
<p>I have a couple apps planned for the new feature that I&rsquo;d planned to release on iPhone, iPad and Mac. I want to use 2026 SDK features, so I&rsquo;d planned to release them as iOS 26, iPadOS 26 and macOS 26 only. As of today, I&rsquo;m delaying the macOS version until I&rsquo;m more comfortable telling people they can update to the new macOS. Part of this is just practical, as I expect to have to re-test the Mac app when some future update to macOS 26 comes out due to a tweaked visual layout.</p>
<p>If you don&rsquo;t <em><strong>have</strong></em> to use Tahoe, I think you should wait a little to see if the reported inconsistencies are going to bother you. I&rsquo;ll take the new features and the inconsistencies together, but it&rsquo;s a trade off you might not need to make.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Desktop database viruses</title>
      <link>https://tewha.net/2021/07/desktop-database-viruses/</link>
      <pubDate>Wed, 21 Jul 2021 03:51:23 +0000</pubDate>
      <guid>https://tewha.net/2021/07/desktop-database-viruses/</guid>
      <description>&lt;p&gt;I was reminded of something today. Let me take you back to Macintosh System Software 6.0. (We&amp;rsquo;d retroactively call it Classic Mac OS 6 now.) Actually, this probably dates back before 6.0. And if you were around then, you probably know all of this. We&amp;rsquo;re going to talk about desktop database viruses.&lt;/p&gt;
&lt;p&gt;Before I go any further, let me specify with 100% clarity: &lt;strong&gt;This problem was fixed 30 years ago, and has absolutely &lt;em&gt;no&lt;/em&gt; bearing on Mac OS X/modern macOS.&lt;/strong&gt; There is probably almost zero overlap between the Apple of 1990 and the Apple of 2021. Modern Apple may make the occasional mistake, but &lt;strong&gt;&lt;em&gt;nothing&lt;/em&gt;&lt;/strong&gt; like what I&amp;rsquo;m about to describe.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I was reminded of something today. Let me take you back to Macintosh System Software 6.0. (We&rsquo;d retroactively call it Classic Mac OS 6 now.) Actually, this probably dates back before 6.0. And if you were around then, you probably know all of this. We&rsquo;re going to talk about desktop database viruses.</p>
<p>Before I go any further, let me specify with 100% clarity: <strong>This problem was fixed 30 years ago, and has absolutely <em>no</em> bearing on Mac OS X/modern macOS.</strong> There is probably almost zero overlap between the Apple of 1990 and the Apple of 2021. Modern Apple may make the occasional mistake, but <strong><em>nothing</em></strong> like what I&rsquo;m about to describe.</p>
<p>Note also that I&rsquo;m going to simplify this significantly by talking about <strong><em>only</em></strong> the 680x0, not the PowerPC. Mac OS on PowerPC changed <strong><em>a lot</em></strong>, but the PowerPC came years after these problems were fixed, so it&rsquo;s irrelevant to this discussion.</p>
<h3 class="wp-block-heading" id="background-resources-and-applications">Background: Resources and applications</h3>
<p>Let&rsquo;s start with the <a href="http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-9.html">Resource Manager</a>. Mac files could contain a data and a resource fork. A resource fork contained one or more (and often many) resources, stored by type and ID. There were a lot of resource types defined for both the system software and applications. Just for example:</p>
<ul>
<li>Icon &ldquo;lists&rdquo; were type <strong>ICN#</strong> resources.</li>
<li>General code segments were stored <strong>CODE</strong> resources.</li>
<li>Windowing code (frames, hit detection, etc) were stored in <strong>WDEF</strong> resources.</li>
<li>Code for custom controls (like buttons) were stored in <strong>CDEF</strong> resources.</li>
<li>Code for custom menus were stored in <strong>MDEF</strong> resources.</li>
<li>Simple black and white icons were <strong>ICON</strong> resources.</li>
<li>Color icons were stored in <strong>cicn</strong> resources.</li>
<li>Applications defined their metadata (&ldquo;This is MacWrite!&rdquo;) with a <strong>BNDL</strong> resources.</li>
<li>Applications defined their document types (&ldquo;This is a MacWrite document; use this icon to display it!&rdquo;) with one <strong>FREF</strong> resource per document type.</li>
</ul>
<p>The resource fork could be viewed as sort of a limited database, each resource having a type and an ID. It wasn&rsquo;t intended to scale, and there were no queries except by sequence or by ID. (Just so nobody jumps on me: IDs were unique within a type only. Much of Apple&rsquo;s System Software relied on this: resources would be extended later with a different type of the same ID so the original resource record wouldn&rsquo;t need to be updated. For example, ICN# defined a black and white icon and its mask. The Macintosh System Software would automatically draw the color icl8 of the same ID on color Macs when possible. This will not be on the exam.)</p>
<p>Applications were built as resource files. Most applications were only resource files. (Some rare applications stored license info or something else in their data forks.)</p>
<p>This information is hard to look up these days, and it doesn&rsquo;t matter materially to the rest of this. The point is that you&rsquo;d build your application, and it would contain code and resources.</p>
<ul>
<li>If you wanted a custom window appearance or behaviour you&rsquo;d put that code in a separate build process and output a WDEF resource. This was all reasonable and by design.</li>
<li>By convention, you&rsquo;d use IDs in a given range (128 to 32,767 for most resource types) and the system would use other IDs (-32,768 to 127 for most resource types).</li>
<li>Apple eventually reserved all resource types not containing at least one uppercase letter for future use.</li>
<li>Nothing actually enforced any of these rules; they were for developer safety, as conflicting with an Apple resource could cause glitches, a failure to launch, or a crash or other bad behaviour somewhere in your application.</li>
</ul>
<p>One of the features of the Resource Manager was that resource files opened later would override files opened earlier. The first resource file opened by the system software was System. (Logically, anyway.) Other resource files were opened, including ultimately your application.</p>
<p>This behaviour was actually critically important to Classic Mac OS! Your custom WDEF, let&rsquo;s say ID 128, was part of the resource chain. If your window specified it should be drawn by WDEF 128, it wasn&rsquo;t referred to as &ldquo;WDEF 128 in your application&rsquo;s resource fork.&rdquo; It was WDEF 128 <em>in your application&rsquo;s resource chain</em>, which happened to be satisfied by your application&rsquo;s WDEF 128.</p>
<p>Likewise, a call to WDEF 0 wasn&rsquo;t really to System WDEF 0, it was to WDEF 0 <em>in the application&rsquo;s resource chain</em>… it just happened to be satisfied by WDEF 0 in System. This Wild West approach was even abused &ldquo;well&rdquo; in some cases, like overriding the System WDEF to change the behaviour to add features. These could patch the behaviour and then call back to the System WDEF. Window shading was done by third parties before Apple got to it. We&rsquo;re still good!</p>
<p>(As an aside, there <strong><em>were</em></strong> other ways to customize window behaviour: <a href="http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/OSUtilities/OSUtilities-170.html">a-trap patches</a> were probably much more commonly used by legitimate code. Classic Mac OS was a wild beast.)</p>
<h3 class="wp-block-heading" id="the-desktop-database">The Desktop database</h3>
<p>One of the things the Macintosh System Software did was track application/file associations. Remember BNDL and FREF? These were part of applications, but they were cached centrally per disk in the desktop database. I don&rsquo;t actually recall how this was done; I&rsquo;m not sure if they were still BNDL and FREF resources. I think probably not. Various actions would copy BNDL and FREF resources from the application to the desktop database (whatever form that took). There was a <a href="http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-483.html#HEADING483-0">Desktop Manager</a>, but it relied on files that applications <em>could</em> (but <em>shouldn&rsquo;t</em>) write to directly.</p>
<p>The desktop database would be automatically opened when a disk was inserted by opening the desktop database file — which meant adding it to the resource chain. And if you&rsquo;ve understood all of the above, you might already see the problem — but don&rsquo;t worry if you don&rsquo;t. I&rsquo;ll explain it!</p>
<h3 class="wp-block-heading" id="pandoras-box-was-open">Pandora&rsquo;s box was open</h3>
<p>Now we&rsquo;ve set the stage. The way the Resource Manager works is perfectly sensible, but the desktop database <strong><em>which was built on top of it</em></strong> doesn&rsquo;t take into account all the quirks of it. Remember I said later opened resource files took priority over earlier resources? <em>Everything overrides System! Ouch!</em> And let&rsquo;s now make it worse: In those days, the System Software didn&rsquo;t protect itself and it was possible to write to various resource forks.</p>
<p>Let&rsquo;s review:</p>
<ul>
<li>Resources in the desktop database are automatically added to the resource chain.</li>
<li>Code resources in the later resource files are prioritized over earlier resource files.</li>
<li>Code is unsigned, and code can write to the system and things considered &ldquo;the system&rdquo; can write to other applications (including modifying their code).</li>
<li>Code can also write to the desktop database.</li>
</ul>
<p>We have everything in place for a viral horror story. Let&rsquo;s go through this with an infected app:</p>
<ul>
<li>You run an infected or delivery application.</li>
<li>The virus spreads itself to the system file.</li>
<li>The virus spreads itself to applications.</li>
<li>The virus spreads itself to the desktop database <em>of all mounted disks, present and future</em>.</li>
</ul>
<p>An infection being caused by running an application is pretty typical stuff. But it&rsquo;s the choice of the desktop database that&rsquo;s the real killer. We don&rsquo;t just have an infected app now, we have an infected <strong><em>disk</em></strong>:</p>
<ul>
<li>Another user inserts the infected disk — the system software immediately adds the desktop database to the resource chain and starts calling code from it, and just like that, the computer is infected!</li>
<li>The virus spreads itself to the system file.</li>
<li>The virus spreads itself to applications.</li>
<li>The virus spreads itself to the desktop database <em>of all mounted disks, present and future</em>.</li>
</ul>
<p>In fact, the desktop database is such a great vector for propagation <strong><em>that I lied above</em></strong>. The <a href="http://virus.wikidot.com/wdef">first successful desktop database virus (WDEF)</a> doesn&rsquo;t actually do steps 2 and 3 <strong><em>ever</em></strong>. We don&rsquo;t have infected applications! We just have the delivery application, which you may never see, and infected desktop databases potentially on any disk we touch. As a result, the intention of WDEF was that it be basically harmless. Unfortunately, it had bugs that made it not harmless. Later desktop database viruses, like <a href="http://virus.wikidot.com/mdef">MDEF/Garfield</a> and <a href="http://virus.wikidot.com/cdef">CDEF</a>, <em>did</em> infect applications however and were intentionally destructive.</p>
<p>It was hard to get rid of permanently. The next user of the infected disk could be you just a few days after you&rsquo;ve painstakingly removed all traces of the virus. Wham, you&rsquo;re infected. Again.</p>
<p>To say this virus spread rapidly was an understatement. It&rsquo;s hard to imagine a more perfect attack vector for viruses! I was in high school at the time, and some of our network shares were infected by admin. That led to every student&rsquo;s disks being infected.</p>
<p>The situation was truly awful. Locking down those network shares so admin didn&rsquo;t casually write to them helped. John Norstad&rsquo;s freeware <a href="https://en.wikipedia.org/wiki/Disinfectant_(software)">Disinfectant</a> (1988) helped, Commercial active virus protection like <a href="https://en.wikipedia.org/wiki/Norton_AntiVirus#Origins">Symantec Antivirus for Mac</a> (1989) helped even more if you weren&rsquo;t perfectly careful. It was hard to be perfectly careful. Symantec Antivirus would scan disks as you inserted them and alert you to processes trying to modify code, for instance.</p>
<h3 class="wp-block-heading" id="system-software-70-saves-the-day">System Software 7.0 saves the day</h3>
<p>Apple solved this in 1991. System Software 7.0 changed the way the desktop database worked, at least on larger volumes. I don&rsquo;t think exactly what they did was publicly documented, but the desktop database was renamed, split and no longer stored in a resource fork. There were likely other fixes to how older style desktop databases were loaded, too, as it solved the problem of viruses being spread as soon as floppies were inserted.</p>
<p>Unfortunately, that didn&rsquo;t stop infections that spread via applications or system files. Some later viruses included <a href="http://virus.wikidot.com/mbdf">MBDF</a>, co-created by <a href="https://en.wikipedia.org/wiki/Mark_Pilgrim">Mark Pilgrim</a> (of Dive Into fame).</p>
<p>But the desktop viruses were <strong><em>the worst</em></strong>.</p>
<h3 class="wp-block-heading" id="epilogue-mac-os-x">Epilogue: Mac OS X</h3>
<p>Over time, System 7 became Mac OS. Mac OS 8/9 became the Classic environment in Mac OS X, whereas a different version of those Mac OS APIs became Carbon. Carbon was a way to build a proper Mac OS X application.</p>
<p>The desktop database viruses were never a problem in the Classic environment, since it didn&rsquo;t auto-load resources from disks. There was still a System, and later opened files still took priority over it, but this wasn&rsquo;t a major problem. Classic was ultimately removed in Mac OS X 10.5.</p>
<p>Meanwhile, resource forks were still supported in Carbon for years. I think the dropping of support for 32-bit applications in Mac OS X 10.15 (2019) finished them off since Carbon was never released in 64-bit form, but they might have survived in more esoteric ways. Custom icons on a file used to be stored in the resource fork, for instance, but this was changed years ago. The resource chain was never a danger in Caron, though, as everything <strong><em>under</em></strong> the APIs was implemented differently.</p>
<p>I&rsquo;m sure there are people with better info than the above, but I think it&rsquo;s basically correct.</p>
]]></content:encoded>
    </item>
    <item>
      <title>How not to write shitty code: Intentional Conditions</title>
      <link>https://tewha.net/2020/04/how-not-to-write-shitty-code-intentional-conditions/</link>
      <pubDate>Sat, 18 Apr 2020 22:56:48 +0000</pubDate>
      <guid>https://tewha.net/2020/04/how-not-to-write-shitty-code-intentional-conditions/</guid>
      <description>&lt;p&gt;I think this is probably going to be a series. I&amp;rsquo;ve read enough shitty code (including my own and that of coworkers I have a lot of respect for) that I think I can offer a few tips on how &lt;em&gt;not&lt;/em&gt; to write shitty code. This is going to be the first, which I call Intentional Conditions.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I think this is probably going to be a series. I&rsquo;ve read enough shitty code (including my own and that of coworkers I have a lot of respect for) that I think I can offer a few tips on how <em>not</em> to write shitty code. This is going to be the first, which I call Intentional Conditions.</p>
<p>When you&rsquo;re writing a condition, you should think carefully about not only what you have to check but <em>why</em> you&rsquo;re checking it. What is the meaning behind the check? How would a human check this? Often, a condition has prerequisites, a primary rule and a list of exceptions. The expression you came up with to express this might not match how you (or anyone else) thinks of it!</p>
<p>For example, let&rsquo;s say we wanted to save a person record. You might need to know the following:</p>
<ul>
<li>That some value of the record has actually changed.</li>
<li>That the record is not a built-in that can never be changed.</li>
<li>That the user has permission to change the record.</li>
</ul>
<p>The code might look like this (and I should warn you, I&rsquo;m not even going to try to write this in a real language, let alone compile it):</p>






<pre tabindex="0"><code>if (!record.isBuiltIn() &amp;&amp; (!record.firstName.equals(oldRecord.firstName) || !record.lastName.equals(oldRecord.lastName) || !record.company.equals(oldRecord.company) || !record.department.equals(oldRecord.department)) &amp;&amp; user.canChange(record)) {
    // can&#39;t save
}</code></pre>
<p>First, stop and break it into a function.</p>






<pre tabindex="0"><code>if (!canSave(record, old_record) {
    // you can&#39;t save this record
}

boolean canSave(record, old_record) {
    return !record.isBuiltIn() &amp;&amp; !(record.firstName.equals(oldRecord.firstName) || !record.lastName.equals(oldRecord.lastName) || !record.company.equals(oldRecord.company) || !record.department.equals(oldRecord.department)) &amp;&amp; user.canChange(record);
}</code></pre>
<p>You&rsquo;ve already improved the condition because you&rsquo;ve given it a name.</p>
<p>Now, think about the rule and the exception. The rule here, I think, is that the record has changed. The exceptions are the reasons you can&rsquo;t save it.</p>






<pre tabindex="0"><code>boolean canSave(record, old_record) {
    boolean hasChanged = (!record.firstName().equals(oldRecord.firstName())
        || (!record.lastName().equals(oldRecord.lastName())
        || (!record.company().equals(company.firstName())
        || (!department().equals(department()));
    return hasChanged &amp;&amp; !record.isBuiltIn() &amp;&amp; user.canChange(record);
}</code></pre>
<p>But that&rsquo;s still going to be a massive pain to debug. So let&rsquo;s use the &ldquo;return early, return often&rdquo; style to make this more readable:</p>






<pre tabindex="0"><code>boolean canSave(record, old_record) {
    boolean hasChanged = (!record.firstName().equals(oldRecord.firstName())
        || (!record.lastName().equals(oldRecord.lastName())
        || (!record.company().equals(company.firstName())
        || (!department().equals(department()));
    if (!hasChanged) {
        return false;
    }

    if (record.isBuiltIn() {
        return false;
    }
    
    if (!user.canChange(record)) {
        return false;
    }
    
    return true;
}</code></pre>
<p>Some would argue that the last two returns should be combined, but I think there&rsquo;s not much difference between returning frequently and relying on short circuit boolean expressions. What matters is how easy it is to debug, and it&rsquo;s much easier to put breakpoints on unexpected returns if they&rsquo;re one per line.</p>
<p>You&rsquo;ll also notice I put <code>hasChanged</code> into a temporary variable. This is 2020, and even if your compiler/optimizer isn&rsquo;t smart enough to produce equally efficient code, unless you&rsquo;re sure this is a bottleneck you can spare the cycle or two to handle that. Naming things helps understand them.</p>
<p>There&rsquo;s a whole argument to be had regarding keeping function results in local variables for easier debugging, but we&rsquo;ve mostly sidestepped it here. You&rsquo;ll be able to tell if the record is built in based on what you hit when you step, for example.</p>
<p>Now remember how I said we should think about the prerequisites, primary rule and the exceptions? Now that we&rsquo;ve written it out this way, I think we&rsquo;re checking things in the wrong order. It&rsquo;s probably more important that function fail early if the user doesn&rsquo;t have the ability to change it. These are more prerequisites than exceptions.</p>
<p>So let&rsquo;s tweak that:</p>






<pre tabindex="0"><code>boolean canSave(record, old_record) {
    if (record.isBuiltIn() {
        return false;
    }

    if (!user.canChange(record)) {
        return false;
    }
    
    boolean hasChanged = (!record.firstName().equals(oldRecord.firstName())
        || (!record.lastName().equals(oldRecord.lastName())
        || (!record.company().equals(company.firstName())
        || (!department().equals(department()));
    if (!hasChanged) {
        return false;
    }
    
    return true;
}</code></pre>
<p>There&rsquo;s still room for improvement: that last <code>if</code> is hard to read, after all. How could we make it better? The next step would is to split off <code>hasChanged</code> as its own function, providing a quick way to compare if two records are equivalent. Then we could drop the temporary variable if we liked.</p>
<p>If we did that, we&rsquo;d end up with a <code>canSave</code> function like this:</p>






<pre tabindex="0"><code>boolean canSave(record, old_record) {
     if (record.isBuiltIn() {
         return false;
     }

    if (!user.canChange(record)) {
        return false;
    }
    
    if (record.valuesEqual(oldRecord)) {
        return false;
    }
    
    return true;
}</code></pre>
<p>Not everyone will love this code, but it&rsquo;s very straightforward to read.</p>
<p>You&rsquo;ll breathe a sigh of relief years from now when you need to debug this! Whether it&rsquo;s optimal or not, it&rsquo;s <em>less shitty</em> than the original.</p>]]></content:encoded>
    </item>
    <item>
      <title>Don’t install Zoom</title>
      <link>https://tewha.net/2020/04/dont-install-zoom/</link>
      <pubDate>Wed, 01 Apr 2020 21:33:39 +0000</pubDate>
      <guid>https://tewha.net/2020/04/dont-install-zoom/</guid>
      <description>&lt;p&gt;BC School District 34 (Abbotsford) has approved Zoom and wants my son to install it, despite me saying I didn&amp;rsquo;t want it installed here. If enough of us stand against it, they&amp;rsquo;ll use something else. Zoom should be disallowed at the provincial level so districts can&amp;rsquo;t make the decision to use it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>BC School District 34 (Abbotsford) has approved Zoom and wants my son to install it, despite me saying I didn&rsquo;t want it installed here. If enough of us stand against it, they&rsquo;ll use something else. Zoom should be disallowed at the provincial level so districts can&rsquo;t make the decision to use it.</p>
<p>Here&rsquo;s a partial list of why you don&rsquo;t want to run Zoom. The problem isn&rsquo;t so much these vulnerabilities as that they keep coming, and Zoom seems to have a sense of complete apathy towards them. Many of these are bad ideas to the point where it&rsquo;s hard to imagine a reasonable programmer would do something that way, which leads me to believe there are probably bad fundamental decisions throughout.</p>
<p>July 2019:</p>
<ul>
<li>Zoom runs a local web server that <a href="https://appleinsider.com/articles/19/07/08/flaw-in-zooms-mac-client-allows-websites-to-turn-on-user-cameras-without-permission">allows computers with Zoom installed to have their cameras</a> remotely hijacked and re-install software without permission.</li>
<li>Having initially refused, Zoom <a href="https://appleinsider.com/articles/19/07/09/zoom-to-patch-flaw-that-enabled-access-to-mac-webcams">eventually relents and agrees to fix the flaw (later)</a>.</li>
<li>Presumably, because Apple told them that it was going to <a href="https://appleinsider.com/articles/19/07/10/apple-removes-zoom-web-server-in-stealth-mac-update">block their software from running</a>. (This is the first time Apple has done this with a “legitimate” software package.)</li>
</ul>
<p>March 2020:</p>
<ul>
<li>“Zoom bombing” <a href="https://threatpost.com/as-zoom-booms-incidents-of-zoombombing-become-a-growing-nuisance/154187/">allows hackers to join video conferences</a>. Mostly used for porn advertising.</li>
<li>Additionally, they <a href="https://www.businessinsider.com/zoom-sued-allegedly-sharing-data-with-facebook-2020-3">share data without permission with Facebook</a> against their own privacy policy.</li>
<li>Despite marketing, <a href="https://theintercept.com/2020/03/31/zoom-meeting-encryption/">Zoom chats aren&rsquo;t end-to-end encrypted</a>.</li>
</ul>
<p>April 2020 (so far):</p>
<ul>
<li>Two new <a href="https://threatpost.com/two-zoom-zero-day-flaws-uncovered/154337/">vulnerabilities discovered in Mac client</a>.</li>
<li>Attackers can <a href="https://arstechnica.com/information-technology/2020/04/unpatched-zoom-bug-lets-attackers-steal-windows-credentials-with-no-warning/">use Zoom to steal users’ Windows credentials with no warning</a>.</li>
<li>Zoom is <a href="https://www.vice.com/en_us/article/k7e95m/zoom-leaking-email-addresses-photos">leaking email addresses and phone numbers to strangers</a>.</li>
<li>New York has <a href="https://chalkbeat.org/posts/ny/2020/04/04/nyc-forbids-schools-from-using-zoom-for-remote-learning-after-privacy-concerns-emerge/">banned Zoom from schools</a>.</li>
<li>Bruce recommends IT <a href="https://www.schneier.com/blog/archives/2020/04/security_and_pr_1.html?fbclid=IwAR12BcTgexc56WccdTgesv8oEEfQIeMSSJKhlU-26kKYx56hDwiPPE81JpQ">either lock Zoom down as best you can, or — better yet — abandon the platform altogether</a>.</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Encryption Back Doors</title>
      <link>https://tewha.net/2020/01/encryption-back-doors/</link>
      <pubDate>Thu, 16 Jan 2020 01:40:56 +0000</pubDate>
      <guid>https://tewha.net/2020/01/encryption-back-doors/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s much dishonesty around &amp;ldquo;public requests&amp;rdquo; for Apple to unlock iPhones.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t want anyone thinking I think Apple should set up a back door. I think it would be stupid. But I also think it&amp;rsquo;s reframing the argument away from reality. (Technically, I&amp;rsquo;m sure it would be pretty easy to generate a master decryption key pair and encrypt the device&amp;rsquo;s local key using the public part of the pair. Keeping the private part of the master pair secure is theoretically possible but entirely impractical.)&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>There&rsquo;s much dishonesty around &ldquo;public requests&rdquo; for Apple to unlock iPhones.</p>
<p>I don&rsquo;t want anyone thinking I think Apple should set up a back door. I think it would be stupid. But I also think it&rsquo;s reframing the argument away from reality. (Technically, I&rsquo;m sure it would be pretty easy to generate a master decryption key pair and encrypt the device&rsquo;s local key using the public part of the pair. Keeping the private part of the master pair secure is theoretically possible but entirely impractical.)</p>
<p>But even if Apple were to agree to add a back door, it <em>would not help</em> get into any currently locked iPhones. Existing iPhones have no back door installed, and would have to be unlocked to install it. If you can unlock an iPhone, you don&rsquo;t need to install new software to help unlock it! Unless there&rsquo;s a known vulnerability (which other parties would know about, too) it&rsquo;s mathematically impossible for Apple to offer much help in unlocking an iPhone.</p>
<p>So there&rsquo;s no argument about whether Apple should or can unlock these phones. The argument is if we want all phones unlockable by Apple or whoever else holds a copy of the key in the future (and for certain the US government would do whatever it needed to in order to get a copy).</p>
<p>If Apple were to be forced to install a back door, I hope it is only done to US devices. I also think that if Apple is forced to generate a back door for US phones it should look to relocate its operations and development to a safer country.</p>]]></content:encoded>
    </item>
    <item>
      <title>No, it’s not worse</title>
      <link>https://tewha.net/2019/10/no-its-not-worse/</link>
      <pubDate>Mon, 28 Oct 2019 21:09:21 +0000</pubDate>
      <guid>https://tewha.net/2019/10/no-its-not-worse/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s an article in TidBITS I really enjoyed: &lt;a href=&#34;https://tidbits.com/2019/10/21/six-reasons-why-ios-13-and-catalina-are-so-buggy/&#34;&gt;Six Reasons Why iOS 13 and Catalina Are So Buggy&lt;/a&gt;. Unfortunately, while the actual points in the article are great, both the headline and introduction are… sensationalist. It&amp;rsquo;s a list with a headline designed to grab your intention.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>There&rsquo;s an article in TidBITS I really enjoyed: <a href="https://tidbits.com/2019/10/21/six-reasons-why-ios-13-and-catalina-are-so-buggy/">Six Reasons Why iOS 13 and Catalina Are So Buggy</a>. Unfortunately, while the actual points in the article are great, both the headline and introduction are… sensationalist. It&rsquo;s a list with a headline designed to grab your intention.</p>
<p>The problem with macOS Catalina and iOS 13 isn&rsquo;t that they’re unusually bad. The problem is they’re <em>exactly the same</em> quality as (nearly) every other major release of macOS and iOS, and it just isn’t acceptable anymore. A further problem is that Apple is actually trying to fix these problems this cycle by rapidly releasing fixes, but the software is just too complex for that to work well.</p>
<p>The six points listed are <em>absolutely</em> the reason. But saying “this is unusually bad” is not just wrong but <em>counterproductive</em>. As long as we keep justifying bugs in major releases as “well, it’s not usually this bad” we give them an excuse to continue.</p>
<p>Let me be clear: No, it’s always been this bad. So much so that I <a href="/2016/02/we-need-better/">wrote about this</a> in 2016. As long as things keep going this way, it’s always going to <strong>continue</strong> to be this bad. It’s time to accept a simple truth: This is not a one off, any more than previous releases were. Until things change, the quality isn&rsquo;t going to improve.</p>
<p>The first step to solving a problem is to acknowledge its existence. When faced with reality, choose to believe reality.</p>]]></content:encoded>
    </item>
    <item>
      <title>Multithreaded Core Data</title>
      <link>https://tewha.net/2017/02/multithreaded-core-data/</link>
      <pubDate>Thu, 09 Feb 2017 22:28:34 +0000</pubDate>
      <guid>https://tewha.net/2017/02/multithreaded-core-data/</guid>
      <description>&lt;p&gt;This year I worked on a Core Data application. All of the parts of its sync were in a single file, which as a result had too much state tracking. The result wasn&amp;rsquo;t just complicated, it was dangerous. Should a state change be missed, the operation would never complete.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This year I worked on a Core Data application. All of the parts of its sync were in a single file, which as a result had too much state tracking. The result wasn&rsquo;t just complicated, it was dangerous. Should a state change be missed, the operation would never complete.</p>
<p>I resolved this by breaking it into many <code>NSOperation</code> subclasses. Because of the new design, it should have supported multithreading a large portion of the sync. But when I allowed those operations to operate concurrently (to a limit, more on that in another post), the application would get into thread deadlocks that I couldn&rsquo;t understand.</p>
<p>Eventually, I actually read what the debugger was telling me. It turns out that my multi-threaded code was all running on a single thread. I had a Core Data context for each operation and was using private queues, surely this would be enough?</p>
<p>It&rsquo;s not. My expectations were set wrong by misunderstanding of <code>performBlockAndWait:</code> based on reading too much into <code>NSPrivateQueueConcurrencyType</code>. Apparently this is something discussed in WWDC sessions, but not in Apple&rsquo;s <a href="https://developer.apple.com/reference/coredata/nsmanagedobjectcontext/1506364-performblockandwait?language=objc">NSManagedObjectContext reference</a> and I&rsquo;d somehow missed it.</p>
<p>Given that I was using a managed object context with a private queue, I thought <code>performBlockAndWait:</code> blocks were being executed on the private queue.</p>
<p><strong>That&rsquo;s not how it works.</strong></p>
<p>I was straightened out by <a href="https://twitter.com/bjhomer/status/827034731896123392">BJ Homer on Twitter</a>:</p>
<blockquote>
<blockquote>
<p>@tewha If you use <code>performBlockAndWait</code>, it will prefer to run on the caller’s thread if possible. Just has to obtain a lock first.</p>
</blockquote>
</blockquote>
<p>In fact, calls to <code>performBlockAndWait:</code> make the current thread wait until it can get Core Data concurrency locks, then executes on the current thread. This isn&rsquo;t documented, but neither was my assumption of how things worked.</p>
<p>In my case, this was the main thread because I was executing code in AFNetworking completion blocks, which <a href="http://cocoadocs.org/docsets/AFNetworking/3.1.0/Classes/AFURLSessionManager.html#//api/name/completionQueue">default to the main queue</a>. As I had assumed this code would not be run from the main thread, locks here conflicted with those I&rsquo;d constructed on other threads and caused the deadlock.</p>
<p>I fixed it by dispatching the bulk of my completion blocks to a dedicated background queue.</p>
<p>What does this really mean?</p>
<p>Be dumb about Core Data! Don&rsquo;t make assumptions about which thread your code will run on. Even if you&rsquo;re right, there&rsquo;s no guarantees about the future.</p>
<p><code>performBlockAndWait</code> calls your block in an environment where it can access Core Data via the target context and waits for the code to complete. You should not assume anything about the thread.</p>
<p><code>performBlock</code> calls your block in an environment where it can access Core Data via the target context and doesn&rsquo;t wait for the code to complete. You should not assume anything about the thread.</p>]]></content:encoded>
    </item>
    <item>
      <title>15 months with my Apple Watch</title>
      <link>https://tewha.net/2016/12/15-months-with-my-apple-watch/</link>
      <pubDate>Mon, 12 Dec 2016 17:31:50 +0000</pubDate>
      <guid>https://tewha.net/2016/12/15-months-with-my-apple-watch/</guid>
      <description>&lt;p&gt;Recently, CBC posted &lt;a href=&#34;http://www.cbc.ca/news/technology/smartwatches-struggling-android-wear-apple-watch-samsung-1.3888030&#34;&gt;Still don&amp;rsquo;t own a smartwatch? You&amp;rsquo;re not alone&lt;/a&gt;. First, let me say I agree with the author that not everyone needs or wants a smartwatch. I certainly don&amp;rsquo;t need one, but did want one. I got an Apple Watch as an early birthday present last September or October. And I really do enjoy it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently, CBC posted <a href="http://www.cbc.ca/news/technology/smartwatches-struggling-android-wear-apple-watch-samsung-1.3888030">Still don&rsquo;t own a smartwatch? You&rsquo;re not alone</a>. First, let me say I agree with the author that not everyone needs or wants a smartwatch. I certainly don&rsquo;t need one, but did want one. I got an Apple Watch as an early birthday present last September or October. And I really do enjoy it.</p>
<p>Other than time, there&rsquo;s a few things I use my Apple Watch for every day. Added up, I&rsquo;m very happy with the purchase. I&rsquo;m not sure I&rsquo;d get stainless steel again, but at the time I was worried about the glass screen. I wear it whenever I&rsquo;m awake.</p>
<p><img src="/wp-content/uploads/2016/12/apple-watch-1-225x300.jpg" alt="My Apple Watch"></p>
<ul>
<li>Messages. I love just getting a tap on my wrist. There&rsquo;s an entirely different feeling to receiving a message on the watch vs. my phone. Whereas my phone and its text tone says &ldquo;look at me,&rdquo; that little tap from my watch tells me &ldquo;when you feel like it, I&rsquo;ve got something for you.&rdquo;</li>
<li>Screening calls. I usually turn the ringer off on my phone. Instead, I get a tap on my wrist when a call comes in, and it tells me who it is. If I want to answer, I&rsquo;ll pull out my phone and answer. I could absolutely do this with my phone, and I used to, but this is just easier. (I have used the speaker, and the microphone quality isn&rsquo;t bad.)</li>
<li>Apple Pay. To pay for most things, I tap the side button twice. It brings up my credit cards. But it&rsquo;s actually more secure than a real credit card: Take the watch off my wrist, and it locks. I&rsquo;m looking forward to more places accepting Apple Pay so I don&rsquo;t need to carry my cards everywhere, but it&rsquo;s already available enough to be used daily. (This is in Canada.)</li>
<li>Sunrise/sunset. I know there&rsquo;s a lot of ways to do this, but I find the Solar face unbelievably intuitive. It also nicely demonstrates the dark despair of living in the Vancouver area in winter. Give us Vancouverites a break, please, if we get bummed out this time of year. (When I showed the solar face to a coworker, his first question was &ldquo;What&rsquo;s the horizontal line?&rdquo; &ldquo;That&rsquo;s the sun.&rdquo; &ldquo;Oh. I thought we had more than that.&rdquo; Nope!)</li>
<li>Movement reminders. My job is sitting at the computer. I could have my computer remind me every hour to stand up (in fact, I used to do this) but having the watch monitor me means I&rsquo;m only reminded in hours I&rsquo;ve been sitting.</li>
<li>Unlocking my Mac. I can&rsquo;t believe I forgot this in my first draft! I type my computer password in once per day now. The rest of the time the computer just sees the watch beside it and lets me in.</li>
</ul>
<p>If I take it off the charger at 6am it&rsquo;ll usually last until 6pm the next day. But if I forget to charge it overnight, charging it while I get ready in the morning will guarantee it makes it through the day.</p>
<p>Current Canadian starting price is $399 for the 42mm version of the Series 1.</p>
<p>I bought my wife an Apple Watch for her birthday, too. There&rsquo;s a few differences in our experience:</p>
<ul>
<li>She got the 38mm Sport in pink. (This model has the glass screen, but that&rsquo;s been fine. It&rsquo;s even a little brighter than mine.)</li>
<li>While her battery makes it through the day (at least since one of the earliest updates), I don&rsquo;t think there&rsquo;s any way she&rsquo;d get 36 hours out of it.</li>
<li>She doesn&rsquo;t wear hers at home a lot of the time, but puts it on if she&rsquo;s going out. At work she&rsquo;s able to read messages throughout the day, which she wouldn&rsquo;t be able to on her phone. If she&rsquo;s out for fun, she uses it to screen notifications and calls as well since it requires less of her attention than fetching the phone.</li>
<li>She doesn&rsquo;t care about sunrise/sunset, and uses the Butterflies face instead.</li>
<li>She also uses it for Apple Pay. But this is <em>more</em> critical for her, since she carries a lot less at work. Luckily she works at a restaurant, so if it fails for some reason I get to pay when I pick her up. This has happened only once or twice, and only in the early days or when we&rsquo;ve got new credit cards.</li>
<li>Her fluoroelastomer band discoloured after about 11 months. Mine was still fine. This might be the chemicals she works with, but it might just be that the lavender colour doesn&rsquo;t hold up as well. We picked up a replacement nylon band.</li>
</ul>
<p>To me, this quote from the article completely demonstrates why you might want a smartwatch:</p>
<blockquote>
<p>So far, &ldquo;there&rsquo;s not a great use case for a smartwatch,&rdquo; said Jitesh Ubrani, a senior research analyst with market intelligence firm IDC, who studies mobile technology. &ldquo;A lot of what these devices can do, they&rsquo;re essentially just mimicking the phone.&rdquo;</p>
</blockquote>
<p>This is both absolutely right and wrong, because it presents but ignores the use case: You can do it from your wrist without pulling out your phone.</p>
<p>If you don&rsquo;t mind picking up your phone whenever it demands your attention, great. You can trim the notifications down a lot, after all. But if you want to put your phone in your pocket and keep it there most of the time, at your desk or while out… that&rsquo;s a big part of what the watch is for. You can decide if it&rsquo;s worth the money for you, but it was for me.</p>
<p>Aside from the stand notifications, I haven&rsquo;t even started the fitness stuff. That&rsquo;s still to come.</p>]]></content:encoded>
    </item>
    <item>
      <title>We need better</title>
      <link>https://tewha.net/2016/02/we-need-better/</link>
      <pubDate>Thu, 04 Feb 2016 04:23:58 +0000</pubDate>
      <guid>https://tewha.net/2016/02/we-need-better/</guid>
      <description>&lt;p&gt;Recently, a number of reporters have put on their very best nostalgic glasses to look at the history of Apple software.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.theverge.com/2016/2/3/10900612/walt-mossberg-apple-iphone-ios-mac-osx-app-problems&#34;&gt;Walt Mossberg&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In the last couple of years, however, I’ve noticed a gradual degradation in the quality and reliability of Apple’s core apps, on both the mobile iOS operating system and its Mac OS X platform. It’s almost as if the tech giant has taken its eye off the ball when it comes to these core software products, while it pursues big new dreams, like smartwatches and cars.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently, a number of reporters have put on their very best nostalgic glasses to look at the history of Apple software.</p>
<p><a href="http://www.theverge.com/2016/2/3/10900612/walt-mossberg-apple-iphone-ios-mac-osx-app-problems">Walt Mossberg</a>:</p>
<blockquote>
<p>In the last couple of years, however, I’ve noticed a gradual degradation in the quality and reliability of Apple’s core apps, on both the mobile iOS operating system and its Mac OS X platform. It’s almost as if the tech giant has taken its eye off the ball when it comes to these core software products, while it pursues big new dreams, like smartwatches and cars.</p>
</blockquote>
<p><a href="http://www.loopinsight.com/2016/02/03/about-walt-mossberg-and-apples-app-problem/">Jim Dalrymple</a>:</p>
<blockquote>
<p>It’s just not like Apple to release software that is so broken.</p>
</blockquote>
<p>Although the headline is &ldquo;apps,&rdquo; both articles actually talk about a wide variety of Apple software including the core OS.</p>
<p>Look, I&rsquo;m not here to argue that Apple&rsquo;s software is perfect. I think it&rsquo;s pretty good and it&rsquo;s getting better, but that&rsquo;s beside the point. What I find ridiculous is the assertion that &ldquo;this used to be great.&rdquo; Frankly, it&rsquo;s setting the bar way too low.</p>
<p>Don&rsquo;t believe me? Let&rsquo;s look over some quotes about Apple&rsquo;s software quality. See if you can guess for what Apple release it was written. Most of these are quotes from the time, but some are in retrospect.</p>
<p>Note: Although I&rsquo;m presenting these as quotes, I&rsquo;ve stripped the version number, keywords, old application names and technologies. Further, I&rsquo;ve been bad and have <strong>not</strong> marked those edits in the text, so please check the original story for the real quote. This is all done to make the game more entertaining. I hope the original authors understand this comes from the very best place.</p>
<p>Our first quote is about a broken installer:</p>
<blockquote>
<p>The release was pulled due to a mistake at Apple, in which some components were not included in the installer.</p>
</blockquote>
<p>This was said about 1996&rsquo;s System 7.5.4 (Source: <a href="https://en.wikipedia.org/w/index.php?title=System_7&amp;oldid=690637508">Wikipedia&rsquo;s System 7 article</a>).</p>
<p>Next is about Wi-Fi problems introduced in an OS update:</p>
<blockquote>
<p>The Mac OS X update installed fine but I lost networking including ability to talk to my Apple Airport Extreme.</p>
</blockquote>
<p>This was said about 2003&rsquo;s Jaguar 10.2.8 (Source: CNET&rsquo;s <a href="http://www.cnet.com/news/special-report-troubleshooting-pulled-mac-os-x-10-2-8/">Troubleshooting (pulled) Mac OS X 10.2.8</a>)</p>
<p>Now let&rsquo;s talk lack of polish:</p>
<blockquote>
<p>But that’s not to say that this initial release is all sunshine and daisies. I ran across quite a few bugs and flaws in the software as I tested it, and while none are significant enough to recommend against upgrading, this strikes me as the least polished major iOS update in quite some time.</p>
</blockquote>
<p>This was 2011&rsquo;s release of iOS 5. (Source: <a href="http://www.macworld.com/article/1162962/ios_5_review_ambitious_update_rings_in_the_changes.html">iOS 5 Review: Ambitious update rings in the changes</a>)</p>
<p>Next, we&rsquo;ve got a quote about data corruption:</p>
<blockquote>
<p>Just connecting a drive using this technology to a Mac running OS X can ruin the data on the drive. The problem does not occur with earlier versions of Mac OS X, however.</p>
</blockquote>
<p>This was said about 2003&rsquo;s Panther 10.3 (Source: Macintouch&rsquo;s &ldquo;<a href="http://www.macintouch.com/panfirewire.html">Panther FireWire Bug</a>&rdquo;)</p>
<p>On inconsistent UI:</p>
<blockquote>
<p>Such basic design flaws demonstrate a lack of unity among Apple&rsquo;s development team and a lack of overall coordination and user design standards.</p>
</blockquote>
<p>This was said about 2005&rsquo;s Tiger 10.4 (Source: &ldquo;<a href="http://www.macintouch.com/tigerreview/tiger2.html">Macintoch&rsquo;s Tiger Review</a>&rdquo;)</p>
<p>On security problems:</p>
<blockquote>
<p>Apple has significantly lowered the bar for malicious entities to install and execute damaging code in OS X.</p>
</blockquote>
<p>This was said about 2005&rsquo;s Tiger 10.4 (Source: <a href="http://www.stephan.com/widgets/zaptastic/">blueprint for a widget of mass destruction</a>)</p>
<p>On updates that don&rsquo;t work:</p>
<blockquote>
<p>Apple support drones are getting an earful from Mac users who are experiencing frozen Macs while trying to update to the latest and greatest version of OS X.</p>
</blockquote>
<p>This was said about 2007&rsquo;s Leopard 10.5 (Source: <a href="http://www.theregister.co.uk/2007/10/27/leopard_install_problems/">Dreaded Blue Screen of Death mars some Leopard installs</a>)</p>
<p>On applications being broken:</p>
<blockquote>
<p>Users are reporting a significant number of applications being affected by the issue, including Microsoft Office, older versions of Adobe Photoshop, and various other applications…</p>
</blockquote>
<p>This was said about a 2012 security update to Snow Leopard (Source: <a href="http://www.macrumors.com/2012/02/03/snow-leopard-security-update-kills-powerpc-apps-using-rosetta/">Snow Leopard Security Update Kills PowerPC Apps Using Rosetta</a>)</p>
<p>On sideways motion:</p>
<blockquote>
<p>It has gotten mixed reviews from customers, so far (like other recent versions of Mac OS X, come to think of it). There are real technical and usability improvements, but these are obscured by interface changes and special effects.</p>
</blockquote>
<p>This was said about the 2011 release of Lion (Source: Macintouch&rsquo;s <a href="http://www.macintouch.com/specialreports/lion/review4.html#conclu">Mac OS X 10.7 Lion Review</a>)</p>
<p>It&rsquo;s absolutely true Apple&rsquo;s shipped some stinkers like <code>discoveryd</code>, but that&rsquo;s nothing new. If we want better, the most important thing is to start from reality. A narrative shared by the blogosphere is different from fact.</p>
<p>So let&rsquo;s start from reality: We don&rsquo;t need a return to the &ldquo;golden era&rdquo; (which may not even have been any better). We need better.</p>
<p><em>Note: I reserve the right to add new examples if I feel like it. I&rsquo;m not a reporter, and this isn&rsquo;t a news story.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Info.plist for command line tools</title>
      <link>https://tewha.net/2015/03/info-plist-for-command-line-tools/</link>
      <pubDate>Thu, 12 Mar 2015 05:56:07 +0000</pubDate>
      <guid>https://tewha.net/2015/03/info-plist-for-command-line-tools/</guid>
      <description>&lt;p&gt;In the past if you wanted to include data in your command line app, you could either include it in a separate file or do some linker trickery to embed it. Personally, I never really got into the linker trickery (though it&amp;rsquo;s probably the better solution of the two).&lt;/p&gt;
&lt;p&gt;For a while, though, Xcode has supported a build option &lt;strong&gt;Create Info.plist Section In Binary&lt;/strong&gt;, also known as &lt;code&gt;CREATE_INFOPLIST_SECTION_IN_BINARY&lt;/code&gt;. If on, this will embed the target&amp;rsquo;s Info.plist into the executable as a data segment.&lt;/p&gt;
&lt;p&gt;I couldn&amp;rsquo;t find any documentation on how to get it out, though. After a lot of searching, I came up with &lt;code&gt;getsectbyname&lt;/code&gt;. This is defined in &lt;strong&gt;mach-o/getsect.h&lt;/strong&gt; like so:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In the past if you wanted to include data in your command line app, you could either include it in a separate file or do some linker trickery to embed it. Personally, I never really got into the linker trickery (though it&rsquo;s probably the better solution of the two).</p>
<p>For a while, though, Xcode has supported a build option <strong>Create Info.plist Section In Binary</strong>, also known as <code>CREATE_INFOPLIST_SECTION_IN_BINARY</code>. If on, this will embed the target&rsquo;s Info.plist into the executable as a data segment.</p>
<p>I couldn&rsquo;t find any documentation on how to get it out, though. After a lot of searching, I came up with <code>getsectbyname</code>. This is defined in <strong>mach-o/getsect.h</strong> like so:</p>






<pre tabindex="0"><code>extern const struct section_64 *getsectbyname(
    const char *segname,
    const char *sectname);</code></pre>
<p>(There&rsquo;s a 32-bit version as well, but I was only interested in 64-bit.)</p>
<p>One of the fields in <code>section_64</code> was the address of the data in memory, another its size. Easy to wrap with a <code>NSData</code>, right?</p>
<p>Not so fast. This worked in debug <em>and</em> release builds when run in Xcode, but didn&rsquo;t work when run on Terminal or Instruments. There, accessing the raw bytes caused a segmentation fault.</p>
<p><a href="https://twitter.com/gparker/status/575527435539771392">A tweet from Greg Parker</a> put me on track.</p>
<p>The difference turned out to be <a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization">Address space layout randomization (ASLR)</a>. You can read all about it on Wikipedia, but the gist of it is that in order to make it harder to exploit a vulnerability many operating systems have implemented a system where executables are randomly located in the address space. This makes it harder for injected code to access application or system code. The results returned by <code>getsectbyname</code> don&rsquo;t take ASLR into account.</p>
<p>Instead of using <code>getsectbyname</code>, I had to use <code>getsectiondata</code>. <code>getsectiondata</code> would return a pointer to the exact data I needed. It took me quite a while to find anything relevant online.</p>
<p>It&rsquo;s declared like this:</p>






<pre tabindex="0"><code>extern uint8_t *getsectiondata(
    const struct mach_header *mhp,
    const char *segname,
    const char *sectname,
    unsigned long *size);</code></pre>
<p>But what&rsquo;s that fist thing, the <code>mach_header</code>?</p>
<p>It took me a long time to find anything relevant, but I eventually found out that I needed to use <code>_mh_execute_header</code> from <strong>mach-o/ldsyms.h</strong>.</p>
<p>The resulting code looks like this, and works:</p>






<pre tabindex="0"><code>#include &amp;lt;mach-o/getsect.h&amp;gt;
#include &amp;lt;mach-o/ldsyms.h&amp;gt;

- (instancetype)init {
    self = [super init];
    if (!self) return nil;
    
    NSError *e;
    unsigned long size;
    void *ptr = getsectiondata(&amp;_mh_execute_header, &#34;__TEXT&#34;, &#34;__info_plist&#34;, &amp;size);
    NSData *plistData = [NSData dataWithBytesNoCopy:ptr length:size freeWhenDone:NO];
   _infoPlistContents = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:NULL error:&amp;e];

   return self;
}</code></pre>
<p>This only works in the application; if you need to do this from a dynamic library, try <a href="http://stackoverflow.com/questions/19848567/how-to-get-the-build-uuid-in-runtime-and-the-image-base-address/22674561#22674561">this approach from Cédric Luthi</a>.</p>
<p>Full credit to those two, but I wanted to post something about this so that future searches might find it. Thanks, guys!</p>]]></content:encoded>
    </item>
    <item>
      <title>About</title>
      <link>https://tewha.net/about/</link>
      <pubDate>Sat, 07 Feb 2015 00:51:33 +0000</pubDate>
      <guid>https://tewha.net/about/</guid>
      <description>&lt;p&gt;My name is Steven Fisher. I&amp;rsquo;m a computer programmer in Abbotsford, BC.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Past projects&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve worked at Discovery Software all of my career. We&amp;rsquo;re a small software company specializing in the K12 education market.&lt;/p&gt;
&lt;p&gt;I was lead programmer on the original InteGrade/reMark for DOS and Windows.&lt;/p&gt;
&lt;p&gt;I also co-created and ended up leading InteGrade Pro for Macintosh, DOS and Windows.&lt;/p&gt;
&lt;p&gt;I wrote the first version of Principalm for Palm, and the code that would later become Principalm Connect.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>My name is Steven Fisher. I&rsquo;m a computer programmer in Abbotsford, BC.</p>
<p><strong>Past projects</strong></p>
<p>I&rsquo;ve worked at Discovery Software all of my career. We&rsquo;re a small software company specializing in the K12 education market.</p>
<p>I was lead programmer on the original InteGrade/reMark for DOS and Windows.</p>
<p>I also co-created and ended up leading InteGrade Pro for Macintosh, DOS and Windows.</p>
<p>I wrote the first version of Principalm for Palm, and the code that would later become Principalm Connect.</p>
<p><strong>Current projects</strong></p>
<p>I&rsquo;ve written and maintained the iOS version of Principalm, Teacherpalm and Rubrix.</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>Defending Facebook</title>
      <link>https://tewha.net/2014/09/defending-facebook/</link>
      <pubDate>Fri, 12 Sep 2014 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2014/09/defending-facebook/</guid>
      <description>&lt;p&gt;You know what I really hate? Defending Facebook.&lt;/p&gt;
&lt;p&gt;CBC has a story right now on how &lt;a href=&#34;http://www.cbc.ca/newsblogs/yourcommunity/2014/09/facebook-messenger-found-to-be-tracking-a-lot-more-data-than-you-think.html&#34;&gt;Facebook Messanger captures more data than you think&lt;/a&gt;. And thanks to how inaccurate that story is, now I have to defend Facebook. Way to make my day, CBC.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>You know what I really hate? Defending Facebook.</p>
<p>CBC has a story right now on how <a href="http://www.cbc.ca/newsblogs/yourcommunity/2014/09/facebook-messenger-found-to-be-tracking-a-lot-more-data-than-you-think.html">Facebook Messanger captures more data than you think</a>. And thanks to how inaccurate that story is, now I have to defend Facebook. Way to make my day, CBC.</p>
<h2 id="its_replacing_a_web_app">It’s replacing a web app</h2>
<p>Do you care if Facebook knows which way you hold your phone or which UI elements you use <strong>within the Messenger app</strong> to work?</p>
<p>How you use the UI is useful to them in aggregate, as it helps them improve the UI if they find people taking inefficient paths, backing out of screens immediately (they probably tapped the wrong thing), etc. They can certainly tell all these things if you use the website; that’s just part of how the web works.</p>
<p>I’m not a fan of analytics and I wouldn’t do it in my own apps. First, if you don’t burst those transmissions with other data, it’ll drain the battery a lot faster. Even if you do it’ll drain it a bit faster. But also, unless you explicitly opt into the analytics – and not as part of a general Terms of Service, like you probably did with Facebook – it’s skeevy.</p>
<p>But remember this app is replacing a website. All of this data would be sent to a website from a web browser anyway. For a company replacing a web browser, building in analytics like this probably seems an obvious choice. Certainly, if you think going back to using the website will save you from Facebook knowing how if you opened this menu here or how you to delete a message you’re wrong.</p>
<p>Going back to my question: Does it matter if Facebook knows which way you hold the phone when you type, to use one of the examples from the CBC article? No, of course not.</p>
<p>I don’t even run basic analytics on this site. I do outsource the creative commons badge on the bottom of this page, and there is a script link to App.net. It’s technically possible that they do something. I write because I enjoy writing. I don’t really care who reads it. I bet CBC runs a lot more analytics. Probably as many as Facebook’s Messenger.</p>
<h2 id="memory_representation">Memory representation</h2>
<p>Zdziarski also makes a point about how credit cards are stored in memory.</p>
<p>Memory is memory; the iPhone never writes swap pages to disk. Everything you do on your computer is stored in memory. It’s all transient, and it all goes away.</p>
<p>Worrying about credit cards being stored in memory is alarmist garbage. If you’re worried about someone connecting a debugger to an app, stop.</p>
<h2 id="private_api">Private API</h2>
<p>Zdziarski says that Facebook Messenger uses private API to get the name of your Wi-Fi SSD.</p>
<p>No, it doesn’t. The Wi-Fi SSID is available as part of the public API since iOS 4. I use this on some of my networking screens to let the user know which network they’re connected to, so my users can tell if two devices are on the same WiFi network.</p>
<p>Holding everything else constant, “No iPhones running MyAppName found on PARKSIDE,” is simply a better message than “No iPhones running MyAppName found on your Wi-Fi.”</p>
<p>I don’t have permission to share the code I use. I didn’t even ask, because I found similiar code on <a href="http://stackoverflow.com/questions/5198716/iphone-get-ssid-without-private-library/15236634#15236634">stackoverflow</a>. The key point here is that <code>CNCopyCurrentNetworkInfo</code> (a public API) returns a <code>NSDictionary</code> of information. If you don’t know what that means, a rough translation is “There’s a call in the public API that tells you everything about the network that Apple thinks its okay for you to know.” The SSID is in there. It’s part of Apple’s public API.</p>
<h2 id="understand_im_not_vouching_for_facebook">Understand, I’m not vouching for Facebook</h2>
<p>I have no idea how the Facebook Messenger app works. For all I know, it’s a giant mess of holes.</p>
<p>But I think if there were real holes here, we’d probably have better examples than looking at the name of your SSID, which button you tapped, or which way you hold the phone to type.</p>
<h2 id="focusing_on_the_wrong_thing">Focusing on the wrong thing</h2>
<p>You’re missing the point when you worry about these kinds of things.</p>
<p>A better thing to worry about: Has Facebook built a system where your messages are really secure, not just from <em>hackers</em> but from <em>them</em>? No.</p>
<p>You should be worried about sending the <strong>contents</strong> of your message through Facebook, whether you’re using the website or the app. Are they going to look at it? Probably not. Could they if they wanted to? Absolutely. Will they if it’s part of a broad data collection warrant? Yes, of course.</p>
<p>If you care about privacy, use a secure system. Facebook isn’t one, but neither is SMS.</p>
<h2 id="by_the_way_did_you_jailbreak_your_phone">By the way, did you jailbreak your phone?</h2>
<p>Just so you know, that disables a lot of Apple’s security precautions. It won’t make a difference here, but if you’re worried about Facebook Messenger’s security with a jailbroken phone… I’m laughing. Worry first about whatever fly-by-night package manager and packages you have installed.</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>Built-in categories</title>
      <link>https://tewha.net/2014/03/built-in-categories/</link>
      <pubDate>Wed, 26 Mar 2014 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2014/03/built-in-categories/</guid>
      <description>&lt;p&gt;&lt;strong&gt;NSIndexPath&lt;/strong&gt; is easier to use than you might think.&lt;/p&gt;
&lt;p&gt;If you read the documentation for the class, you’ll see this:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>NSIndexPath</strong> is easier to use than you might think.</p>
<p>If you read the documentation for the class, you’ll see this:</p>
<blockquote>
<p>Creating Index Paths</p>
<ul>
<li>
<p>indexPathWithIndex:</p>
</li>
<li>
<p>indexPathWithIndexes:length:</p>
</li>
</ul>
<ul>
<li>
<p>initWithIndex:</p>
</li>
<li>
<p>initWithIndexes:length:</p>
</li>
<li>
<p>init</p>
</li>
</ul>
</blockquote>
<p>Yes, you can use these to construct an index path. But you probably don’t want to. UIKit defines a category on <strong>NSIndexPath</strong> specific to <strong>UITableView</strong>’s needs:</p>
<pre><code>// This category provides convenience methods to make it easier to use an NSIndexPath to represent a section and row
@interface NSIndexPath (UITableView)

+ (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section;

@property(nonatomic,readonly) NSInteger section;
@property(nonatomic,readonly) NSInteger row;

@end
</code></pre>
<p>There’s a similar category defined by <strong>UICollectionView</strong>:</p>
<pre><code>@interface NSIndexPath (UICollectionViewAdditions)

+ (NSIndexPath *)indexPathForItem:(NSInteger)item inSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

@property (nonatomic, readonly) NSInteger item NS_AVAILABLE_IOS(6_0);

@end
</code></pre>
<p>The absence of section in this category isn’t significant; the same property is already defined by <strong>NSIndexPath (UITableView)</strong>.</p>
<p>UIKit defines other categories, such as drawing categories on <strong>NSString</strong>.</p>
<p>Why are these separated? Well, <strong>NSIndexPath</strong> is part of Foundation. <strong>UITableView</strong> is part of UIKit. String drawing is added to <strong>NSString</strong> which is part of Foundation, but Foundation, but uses <strong>UIFont</strong> which is part of UIKit. In short, there’s good technical reasons for this to be splatted out. But knowing that is not helpful to us developers.</p>
<p>So how do you find out about these methods? I don’t think there’s a good way to find categories like these in Apple’s class references. Some of them are mentioned in Apple’s less reference-like material. For instance, there’s ”<a href="https://developer.apple.com/library/ios/Documentation/Cocoa/Conceptual/Collections/Articles/IndexPaths.htm">Collections Programming Topics: Index Paths: Storing a Path Through Nested Arrays</a>”:</p>
<blockquote>
<p>In iOS, UITableView and its delegate and data source use index paths to manage much of their content and to handle user interaction. To assist with this, UIKit adds programming interfaces to NSIndexPath to incorporate the rows and sections of a table view more fully into index paths. For more information, see NSIndexPath UIKit Additions. For instance, index paths are used to designate user selections using the tableView:didSelectRowAtIndexPath: delegate method.</p>
</blockquote>
<p>Google searches are probably your best bet, such as <a href="https://www.google.com/#q=nsindexpath+from+row+and+section">index path from row and section</a>.</p>
<p>I hope we’ll see improvements on this in the future.</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>Empathy in pricing</title>
      <link>https://tewha.net/2013/03/empathy-in-pricing/</link>
      <pubDate>Sat, 23 Mar 2013 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/03/empathy-in-pricing/</guid>
      <description>&lt;p&gt;I don’t know much about pricing products as a developer. While I’m a programmer, I don’t have apps of my own yet. So take this with a grain of salt, go ahead and flame me, etc. &lt;strong&gt;These are just my feelings.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But nevertheless, I wanted to share how I &lt;em&gt;feel&lt;/em&gt; about pricing as a &lt;em&gt;user&lt;/em&gt; of software.&lt;/p&gt;
&lt;p&gt;I’m going to start with something bold, then work my way back to it: Never let me perceive your product’s pricing is unstable and currently at a high.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I don’t know much about pricing products as a developer. While I’m a programmer, I don’t have apps of my own yet. So take this with a grain of salt, go ahead and flame me, etc. <strong>These are just my feelings.</strong></p>
<p>But nevertheless, I wanted to share how I <em>feel</em> about pricing as a <em>user</em> of software.</p>
<p>I’m going to start with something bold, then work my way back to it: Never let me perceive your product’s pricing is unstable and currently at a high.</p>
<h2 id="introductory_pricing">Introductory pricing</h2>
<p>Catching introductory pricing is always interesting. I fight a feeling that your product is not worth its full price yet, whether due to bugs or missing features.</p>
<p>I need to make a decision: Is your product’s value enough to justify its current price? Are you really going to make it more valuable to match its price later? Do I want the current features at the current price, or trust that you’ll make it worth its final price later?</p>
<p>Missing introductory pricing doesn’t necessarily raise my hackles. I am annoyed, however, if I was considering your product and you arbitrarily ended the offer without any notice.</p>
<p>Overall, I think introductory pricing is reasonable. Give me a little warning before you end it, though!</p>
<p>Summary:</p>
<ul>
<li>Tell me when (or why) the offer ends.</li>
<li>Tell me what the new price will be.</li>
<li>After the increase, eliminate any trace of the old price and update your site to make the product freshly exciting.</li>
<li>Sticking with your price is better.</li>
</ul>
<h2 id="sales">Sales</h2>
<p>Sales can feel arbitrary, or they can feel generous and deliberate.</p>
<p>It’s perfectly fine to have sales that coincide with a time period that’s knowable but you don’t define. This limits my feeling of arbitrariness on your pricing.</p>
<p>For instance, a Black Friday, Boxing Day or WWDC week sale? I’ll shrug it off when I discover your product a week later as something I missed. Oops.</p>
<p>Likewise, a sale before a new version? Go ahead.</p>
<p>On the other hand, arbitrarily sales give me a feeling of instability. A 50% price drop for the month of March? I’m going to be annoyed when I discover your product in April.</p>
<p>But better yet: Don’t do sales. Putting on my developer hat for a moment, is what you made worth it or not? If it is, it is.</p>
<p>Summary:</p>
<ul>
<li>Stick to time periods with meaning.</li>
<li>Don’t teach me that sales could happen at any time.</li>
<li>Sticking with your price is better.</li>
</ul>
<h2 id="discounts">Discounts</h2>
<p>This doesn’t apply if you’re doing App Store sales, but if you’re doing direct sales you need to be more careful with discounts than some of you are being.</p>
<p>Make sure a discount makes sense to me. If you offer a lower price to someone who purchased something in the past, that’s totally reasonable. If you offer a lower price to everyone who does something and I can still do it, that’s reasonable too. If you offer a lower price to someone for completely arbitrary reasons and I can’t qualify, it’s going to annoy me.</p>
<p>There’s a few exceptions to this. Go ahead and offer discounts to students and teachers, for instance. “We all know” that students are poor, even though most of them probably have more discretionary income than I do. And a good teacher deserves to go through life while being fanned by their admirers. Go ahead and offer to <em>discuss</em> discounts for other groups. Just don’t show me what the discount is and that I don’t qualify for it.</p>
<p>Summary:</p>
<ul>
<li>Go ahead and offer bundles or discount cross grades.</li>
<li>It’s better to tell me discounts may apply in special circumstances than to show me them.</li>
<li>Education is an exception. Go ahead, I won’t feel slighted.</li>
<li>Sticking with your price is better.</li>
</ul>
<h2 id="price_increases">Price increases</h2>
<p>Is your product already under-priced? Go ahead and announce you’re increasing the price at a specific time or event. Then stick to it.</p>
<p>If I’m interested in your product at its old price, I will probably nod and agree with you that you were or are undercharging. And if I catch the price before it goes up, so much the better.</p>
<p>Summary:</p>
<ul>
<li>Tell me what your new price is.</li>
<li>Optionally, give me a reason you’re increasing it. (I mean features; I don’t need to know the details of your business or life.)</li>
<li>Follow through with your plan.</li>
</ul>
<h2 id="conclusions">Conclusions</h2>
<p>What do I think you should do?</p>
<ul>
<li>Set a fair price. Stick with it.</li>
<li>If your product is released at an introductory price, say when it’s ending and what the new price will be.</li>
<li>If your product is under-priced, go ahead and announce and raise the price.</li>
<li>Don’t have arbitrary sales or offer discounts, especially those that hint that your product is unfairly priced the rest of the time.</li>
<li>Most importantly, <strong>do not make me perceive your product’s pricing as unstable and currently at a high</strong>.</li>
</ul>
<p>A price of $15 is more likely to make me a happy buyer than a price of $10 I think will be $5 next month, or was $5 last month.</p>
<p>Maybe the numbers make enough sense that you want to do it anyway. That’s fine, I’m only expressing how I feel about it.</p>]]></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>C99 initializers</title>
      <link>https://tewha.net/2013/02/c99-initializers/</link>
      <pubDate>Fri, 08 Feb 2013 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/02/c99-initializers/</guid>
      <description>&lt;p&gt;You probably know &lt;code&gt;CGRectMake&lt;/code&gt;, but did you know it’s not the only way to make rectangles? It’s not even the best way, really.&lt;/p&gt;
&lt;p&gt;There’s also &lt;a href=&#34;http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fstrin.htm&#34;&gt;C99 initializer syntax&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The main advantage to the C99 syntax is that it gives you some very Objective-C like syntax, where the fields are close to the values rather than implied by positioning. (That’s not to say this is intentionally similar, or that it’s the only advantage. But it is nice.) It also provides type checking, and since fields are named it catches drifts in meaning that you otherwise wouldn’t catch.&lt;/p&gt;
&lt;p&gt;It’s sometimes slightly &lt;em&gt;more&lt;/em&gt; typing, but I use it everywhere now.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>You probably know <code>CGRectMake</code>, but did you know it’s not the only way to make rectangles? It’s not even the best way, really.</p>
<p>There’s also <a href="http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fstrin.htm">C99 initializer syntax</a>.</p>
<p>The main advantage to the C99 syntax is that it gives you some very Objective-C like syntax, where the fields are close to the values rather than implied by positioning. (That’s not to say this is intentionally similar, or that it’s the only advantage. But it is nice.) It also provides type checking, and since fields are named it catches drifts in meaning that you otherwise wouldn’t catch.</p>
<p>It’s sometimes slightly <em>more</em> typing, but I use it everywhere now.</p>
<h2 id="the_syntax">The syntax</h2>
<p>Consider the <code>CGRectMake</code> way to make a rectangle:</p>
<pre><code>CGRect a = CGRectMake(a+c/2, b+d/2, c, d);
</code></pre>
<p>In order to understand this, you need to understand the order of the parameters. You also need to be able to catch the commas easily with your eyes. In this case, that’s pretty easy, but if the expressions were more complicated you’d probably be storing them in a temporary variable first.</p>
<p>The C99 way:</p>
<pre><code>CGRect a = (CGRect){
    .origin.x = a+c/2,
    .origin.y = b+d/2,
    .size.width = c,
    .size.height = d
};
</code></pre>
<p>It’s longer, but it’s more explicit. It’s also very easy to follow what is assigned to what, no matter how long the expression are. It’s also more like an Objective-C method. After all, if <code>CGRect</code> was a class, it would probably look like this:</p>
<pre><code>CGRect a = [[CGRect alloc] initWithOriginX:x originY:y width:w height:h];
</code></pre>
<p>Note that any field you don’t explicitly initialize is initialized to zero. This code, for instance, will create a rectangle with an <code>origin</code> of 0,0.</p>
<pre><code>CGRect smallRect = (CGRect){
    .size = mySize
}
</code></pre>
<p>The C99 syntax is a nice compromise; it’s more compact than class construction, but still names field values.</p>
<h2 id="catching_changes">Catching changes</h2>
<p>Naming fields might seem like extra work, but it’s also extra safety. If the names or meanings of the parameters change, you’re going to get compiler errors. The compiler will help you find these, now! And if you write new code based on the old rules, compiler errors will point out what you’ve done.</p>
<p>This isn’t much of a concern for <code>CGRect</code>; it is how it is. Apple is probably never going to redefine it. But many years ago, QuickDraw used edges for its <code>Rect</code> structure instead of points. If you were still trying to break that habit, the compiler would complain every time you did this:</p>
<pre><code>CGRect a = (CGRect){
    .left = 0,
    .right = 100,
    .top = 0,
    .bottom = 100
};
</code></pre>
<p>In your own code, this may be an active concern to you. You may have <code>structs</code> (or use C libraries that have <code>structs</code>) that will change layout in the future.</p>
<h2 id="type_checking">Type checking</h2>
<p>That’s only the start of C99 initializer coolness, though.</p>
<p>You can also do things like this:</p>
<pre><code>CGRect a = (CGRect){
    .origin = myOrigin,
    .size = computedSize
};
</code></pre>
<p>Here, you’re building a rectangle using a <code>CGPoint</code> and <code>CGSize</code>. The compiler understands that <code>.origin</code> expects a <code>CGPoint</code>, and <code>.size</code> expects a <code>CGSize</code>. You’ve provided that. All’s gravy.</p>
<p>The equivalent code would be <code>CGRectMake(myOrigin.x, myOrigin.y, size.width, size.height)</code>. By using <code>CGRectMake</code> you’re no longer expressing the same kind of meaning to the compiler. It can’t stop you from assigning part of the size to the origin. It also won’t stop you from assigning the width to the height. It doesn’t even give you a good clue about which is the X and Y; if you’ve used APIs that provide vertical coordinates first, you’ll get it wrong. If you’re used to APIs that provide two points or something else (like QuickDraw’s edges) instead of a point and size you’ll also get a compiler error.</p>
<p>You can assign part from a structure and part from floats as well:</p>
<pre><code>CGRect a = (CGRect){
    .origin = myOrigin,
    .size.width = c,
    .size.height = d
};
</code></pre>
<h2 id="drawbacks">Drawbacks</h2>
<p>As I said, this is more typing than <code>CGRectMake</code>. What I didn’t say is that it’s even more typing than you expect, because as of Xcode 4.6, you still can’t autocomplete the field names. You really do need to type all that extra code.</p>
<p>I think this is a good pay off for being able to read the code so easily later, but you may disagree.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The <code>CGRectMake</code> function predates C99. I have no evidence to this effect, but I think if C99 had come first <code>CGRectMake</code> probably wouldn’t exist at all; it’s the sort of crusty function you write when your language has no direct way to perform the initialization. But now it does.</p>
<p>This doesn’t only apply to <code>CGRect</code>. Any of the simple <code>struct</code> types can be initialized this way, such as <code>CGPoint</code>, <code>CGSize</code> and <code>NSRange</code>.</p>
<p>Avantages:</p>
<ul>
<li><strong>Explicit</strong>: You’ve named the parameters.</li>
<li><strong>Type safe</strong>: You’ve provided enough meaning to the compiler that it can <em>help you not screw up</em>.</li>
<li><strong>Easy to read</strong>: Especially with longer expressions, you’ve eliminated needing to scan for commas when you read the code later.</li>
</ul>
<p>Disadvantages:</p>
<ul>
<li><strong>More typing</strong>: You read code a lot more than you type it, so I think this is a great tradeoff.</li>
</ul>
<p>Averaged over time, anything you can screw up you eventually will. Using defensive techniques makes sense. Try it for a while; I think you’ll like it!</p>
<p>Special thanks to:</p>
<ul>
<li>
<p><a href="https://twitter.com/boredzo">Peter Hosey</a> for reminding me how QuickDraw worked and inspiring “Catching changes.”</p>
</li>
<li>
<p><a href="https://twitter.com/luka_bernardi">Luke Bernardi</a> for reminding me that Xcode’s autocompletion can’t suggest field names.</p>
</li>
<li>
<p><a href="https://twitter.com/bjhomer">BJ Homer</a> for tipping me that unnamed fields are initialized to 0.</p>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Why you should use instancetype instead of id</title>
      <link>https://tewha.net/2013/02/why-you-should-use-instancetype-instead-of-id/</link>
      <pubDate>Wed, 06 Feb 2013 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/02/why-you-should-use-instancetype-instead-of-id/</guid>
      <description>&lt;p&gt;In my previous entry, I discussed &lt;a href=&#34;https://tewha.net/2013/01/when-is-id-promoted-to-instancetype/&#34;&gt;when &lt;code&gt;id&lt;/code&gt; will be promoted to &lt;code&gt;instancetype&lt;/code&gt;&lt;/a&gt;. But now that I’ve explained this, I’d like to explain why you should &lt;em&gt;understand&lt;/em&gt; this but not &lt;em&gt;rely&lt;/em&gt; on it. Instead, you should use &lt;code&gt;instancetype&lt;/code&gt; directly.&lt;/p&gt;
&lt;p&gt;Let me start with this bold statement, then I’ll back up and explain it: Use &lt;code&gt;instancetype&lt;/code&gt; whenever it’s appropriate, which is whenever a class returns an instance of that same class.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In my previous entry, I discussed <a href="/2013/01/when-is-id-promoted-to-instancetype/">when <code>id</code> will be promoted to <code>instancetype</code></a>. But now that I’ve explained this, I’d like to explain why you should <em>understand</em> this but not <em>rely</em> on it. Instead, you should use <code>instancetype</code> directly.</p>
<p>Let me start with this bold statement, then I’ll back up and explain it: Use <code>instancetype</code> whenever it’s appropriate, which is whenever a class returns an instance of that same class.</p>
<p>First, some definitions:</p>
<pre><code>@interface Foo:NSObject
- (id)initWithBar:(NSInteger)bar; // initializer
+ (id)fooWithBar:(NSInteger)bar;  // convenience constructor
@end
</code></pre>
<p>For a convenience constructor, you should <strong>always</strong> use <code>instancetype</code>. The compiler does not automatically convert <code>id</code> to <code>instancetype</code>.</p>
<p>For initializer, it’s more complicated. When you type this:</p>
<pre><code>- (id)initWithBar:(NSInteger)bar
</code></pre>
<p>…the compiler will pretend you typed this instead:</p>
<pre><code>- (instancetype)initWithBar:(NSInteger)bar
</code></pre>
<p>This was necessary for ARC. This is why people will tell you it isn’t necessary to use <code>instancetype</code>, though I contend you should. The rest of this answer deals with this.</p>
<p>There’s three advantages:</p>
<ol>
<li><strong>Explicit.</strong> Your code is doing what it says, rather than something else.</li>
<li><strong>Pattern.</strong> You’re building good habits for times it does matter, which do exist.</li>
<li><strong>Consistency.</strong> You’ve established some consistency to your code, which makes it more readable.</li>
</ol>
<h2 id="explicit">Explicit</h2>
<p>It’s true that there’s no <em>technical</em> benefit to returning <code>instancetype</code> from an <code>init</code>. But this is because the compiler automatically converts the <code>id</code> to <code>instancetype</code>. You are relying on this quirk; while you’re writing that the <code>init</code> returns an <code>id</code>, the compiler is interpreting it as if it returns an <code>instancetype</code>.</p>
<p>These are <em>equivalent</em> to the compiler:</p>
<pre><code>- (id)initWithBar:(NSInteger)bar;
- (instancetype)initWithBar:(NSInteger)bar;
</code></pre>
<p>These are not equivalent to your eyes. At best, you will learn to ignore the difference and skim over it. <strong>This is not something you should learn to ignore.</strong></p>
<h2 id="pattern">Pattern</h2>
<p>While there’s no difference with <code>init</code> and other methods, there <strong>is</strong> a different as soon as you define a convenience constructor.</p>
<p>These two are not equivalent:</p>
<pre><code>+ (id)fooWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
</code></pre>
<p>You want the second form. If you are used to typing <code>instancetype</code> as the return type of a constructor, you’ll get it right every time.</p>
<h2 id="consistency">Consistency</h2>
<p>Finally, imagine if you put it all together: you want an <code>init</code> function and also a convenience constructor.</p>
<p>If you use <code>id</code> for <code>init</code>, you end up with code like this:</p>
<pre><code>- (id)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
</code></pre>
<p>But if you use <code>instancetype</code>, you get this:</p>
<pre><code>- (instancetype)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
</code></pre>
<p>It’s more consistent and more readable. They return the same thing, and now that’s obvious.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Unless you’re intentionally writing code for old compilers, you should use <code>instancetype</code> when appropriate.</p>
<p>You should hesitate before writing a message that returns <code>id</code>. Ask yourself: Is this returning an instance of this class? If so, it’s an <code>instancetype</code>.</p>
<p>There are certainly cases where you need to return <code>id</code>; namely, if you’re returning a different class. But you’ll probably use <code>instancetype</code> much more frequently than <code>id</code>.</p>]]></content:encoded>
    </item>
    <item>
      <title>When is id promoted to instancetype?</title>
      <link>https://tewha.net/2013/01/when-is-id-promoted-to-instancetype/</link>
      <pubDate>Mon, 21 Jan 2013 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/01/when-is-id-promoted-to-instancetype/</guid>
      <description>&lt;p&gt;&lt;code&gt;instancetype&lt;/code&gt; is a special type that can be returned from an Objective-C method. It specifies that the return is an object of the same type as the receiving class. In some cases, the compiler promotes an &lt;code&gt;id&lt;/code&gt; return to an instancetype: For instance, despite the definition of &lt;code&gt;[[NSString alloc] init]&lt;/code&gt;, the compiler knows that it returns an &lt;code&gt;NSString&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><code>instancetype</code> is a special type that can be returned from an Objective-C method. It specifies that the return is an object of the same type as the receiving class. In some cases, the compiler promotes an <code>id</code> return to an instancetype: For instance, despite the definition of <code>[[NSString alloc] init]</code>, the compiler knows that it returns an <code>NSString</code>.</p>
<p>When?</p>
<p>This is straight from <a href="http://clang.llvm.org/docs/LanguageExtensions.html#related-result-types">Clang Language Extensions</a>:</p>
<ul>
<li>the first word is “alloc” or “new”, and the method is a class method, or</li>
<li>the first word is “autorelease”, “init”, “retain”, or “self”, and the method is an instance method.</li>
</ul>
<p>Left unsaid is whether it’s better to actually specify <code>instancetype</code> for these rather than rely on automatic promotion of <code>id</code>. Most code I’ve seen relies on the automatic promotion. I’m not sure what combination this is of momentum, readability, compatibility and convention. I’ve kept to using <code>id</code> in these cases, but that’s mostly due to momentum.</p>
<p>However, you should certainly use <code>instancetype</code> if you want to specify that an instance of the receiving class is returned in cases where autopromotion doesn’t occur, such as a convenience factory.</p>
<p>For example, in this case:</p>
<pre><code>MyObject *bar = [MyObject objectWithParameter: foo];
</code></pre>
<p>…you would want <code>MyObject</code> to specify that <code>objectWithParameter</code> returns an <code>instancetype</code> rather than an <code>id</code>.</p>
<p>See also:</p>
<ul>
<li>Mattt Thompson: <a href="http://nshipster.com/instancetype/">instancetype</a>.</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>A primer on @property and dot syntax</title>
      <link>https://tewha.net/2013/01/a-primer-on-property-and-dot-syntax/</link>
      <pubDate>Fri, 18 Jan 2013 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2013/01/a-primer-on-property-and-dot-syntax/</guid>
      <description>&lt;p&gt;Properties were new in Objective-C 2.0, introduced in 2006. While pretty uncontroversial, along with them came dot syntax. Dot syntax is much more controversial.&lt;/p&gt;
&lt;p&gt;In this article, I’ll discuss the advantages of &lt;code&gt;@property&lt;/code&gt; which make it worth using, and discuss “dot syntax.”&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Properties were new in Objective-C 2.0, introduced in 2006. While pretty uncontroversial, along with them came dot syntax. Dot syntax is much more controversial.</p>
<p>In this article, I’ll discuss the advantages of <code>@property</code> which make it worth using, and discuss “dot syntax.”</p>
<h2 id="properties">Properties</h2>
<p>Properties are awesome. A <code>@property</code> declaration formalizes some things that previously had to be explained in comments or by convention.</p>
<p>Without properties, you’d specify a getter and setter like this:</p>
<pre><code>@interface Bar : NSObject
- (void)setFoo: (NSObject *)foo;
- (NSObject *)foo;
@end
</code></pre>
<p>With properties, you can specify it like this:</p>
<pre><code>@interface Bar : NSObject
@property (readwrite, atomic, strong) NSObject *foo;
@end
</code></pre>
<p>Whereas a set accessor defines only the owning object and the new value, a <code>@property</code> declaration specifies the memory management model for the new value. Is the setter going to copy it, own it, or just assign it? With ARC, these become even more useful: You can copy it, specify that it’s kept via a strong reference, specify that it’s a weak, zeroing reference, or specify that it’s a weak reference that could become a dangling pointer.</p>
<p>Further, you can specify whether the property is atomic: If two threads try to access a property at the same time, is the behaviour fully defined?</p>
<p>Even more useful, if your getter and setter are trivial Objective-C can synthesize them for you. (In older compilers, you needed to specify this with <code>@synthesize</code>; in the latest version, the compiler will do this for you.)</p>
<p>Note: If you write your own getter/setter, you’re responsible for making sure it complies with the memory model and atomicity you’ve specified in the <code>@property</code>. The <code>@property</code> is a promise to other compilation units, and your object is not held to that promise by the compiler.</p>
<h2 id="what_is_dot_syntax">What is dot syntax?</h2>
<p>Dot syntax is syntactical sugar for accessing properties. Whereas the <code>@property</code> statement defines the property, dot syntax is an option for <strong>calling</strong> it.</p>
<p>Excluding dot syntax these are equivalent:</p>
<pre><code>_view1.frame = _view2.frame;
[_view1 setFrame: [_view2 frame]];
</code></pre>
<p>There are some unexpected gotchas involving dot syntax. This, for instance, does not compile:</p>
<pre><code>_view1.frame.size.width = 10;
</code></pre>
<p>The reason is it’s equivalent to this:</p>
<pre><code>[_view1 frame].size.width = 10;
</code></pre>
<p>You can’t change a field in a rvalue like this. Instead, you need to do this:</p>
<pre><code>CGFrame frame = _view1.frame;
frame.size.width = 10;
_view1.frame = frame;
</code></pre>
<p>This shows an important distinction: dot syntax may <em>look</em> like struct access, but it isn’t the same thing at all.</p>
<h2 id="using_dot_syntax">Using dot syntax</h2>
<p>In some cases the compiler will even let you get away with dot syntax for methods that aren’t properties. But you really shouldn’t; Objective-C isn’t Visual Basic (where this is supported) and this runs counter to the language. In the past, I’ve seen Apple engineers argue that doing so is taking advantage of a compiler limitation that will probably eventually be fixed. Or maybe it’s a compiler limitation that they’ll never get around to fixing. In either case, it’s taking advantage of a compiler limitation.</p>
<p>There’s a huge grey area here. Some will argue setting a property shouldn’t have side effects, shouldn’t perform an action, or many things between.</p>
<p>Clearly, setting something without side effects is a property. I think most Objective-C developers will agree with this, though some argue that calling code at all makes dot syntax inappropriate. The argument is that it looks like struct access, so it should behave <strong>exactly</strong> like struct access. I don’t agree with this, but some very wise people do.</p>
<p>By UIKit convention, visual side effects (such as changing a frame) is acceptable. Some of these are true properties, complete with a <code>@property</code> definition. Some lack the <code>@property</code> definition, as <code>@proeprty</code> predates much of UIKit but make sense as properties anyway. (I picked UIKit here because it’s more modern than AppKit, but the same applies there.)</p>
<p>However, a method that takes no parameters but does not return a value is clearly <strong>not</strong> a property. Obviously, a method that takes parameters that do not conform to a getter/setter signature does not represent part of a property.</p>
<p>This, while legal under some configurations, is never appropriate:</p>
<pre><code>obj.release;
</code></pre>
<p>Dot syntax should be limited to things that are semantically properties only. Whether you further limit that to things that are only defined with <code>@property</code> is up to you. I do for my own objects, but I prefer to believe that Apple would fix UIKit’s missing <code>@property</code> definitions before enforcing this at a compiler level. If I’m wrong, it’ll be easy enough to remove dot syntax from the affected code. But I think it’s more likely that Apple won’t enforce this at the compiler level.</p>
<p>There are even greyer areas to this. What constitutes a property? For instance, is <code>NSArray</code>’s count a property? I would argue it isn’t; it’s an attribute, a side-effect based on the other properties of the <code>NSArray</code>. But Apple template code uses the count of an array as if it was a property, and the result is not horrible. You could certainly argue it’s wrong, but I view it as just over the line.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Embrace <code>@property</code>. The additional information it supplies regarding memory management and thread safety is great. Not only that, but it’s less code than the old way of declaring your getter and setter.</p>
<p>Use dot syntax where appropriate. You need to decide where the line is for yourself, as there are no hard rules about this. Everyone has an opinion over it, and the only thing you can be sure of is that there’s little consensus, except that some things are always inappropriate.</p>]]></content:encoded>
    </item>
    <item>
      <title>Trimming a level of indent with @synchronized and @autoreleasepool</title>
      <link>https://tewha.net/2012/10/trimming-a-level-of-indent-with-synchronized-and-autoreleasepool/</link>
      <pubDate>Tue, 30 Oct 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/10/trimming-a-level-of-indent-with-synchronized-and-autoreleasepool/</guid>
      <description>&lt;p&gt;I haven’t seen this discussed anywhere, but you can eliminate a level of indentation when using &lt;code&gt;@synchronized&lt;/code&gt; and &lt;code&gt;@autoreleasepool&lt;/code&gt; blocks in a loop or conditionally. This falls naturally as a result of the way the C language works, and how these blocks work, but it took me a while to realize it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I haven’t seen this discussed anywhere, but you can eliminate a level of indentation when using <code>@synchronized</code> and <code>@autoreleasepool</code> blocks in a loop or conditionally. This falls naturally as a result of the way the C language works, and how these blocks work, but it took me a while to realize it.</p>
<p>You may have code that looks like this:</p>
<pre><code>if (_foo) {
    @synchronized(self) {
        // stuff here
    }
}
</code></pre>
<p>This can also be expressed more simply:</p>
<pre><code>if (_foo) @synchronized(self) {
    // stuff here
}
</code></pre>
<p>Note that you can’t use this if your <code>if</code> has an <code>else</code> statement.</p>
<p>This is also true of <code>@autoreleasepool</code>, and may be even more handy there:</p>
<pre><code>for (NSDictionary *item in items) {
    @autoreleasepool {
        // lots of stuff here
    }
}
</code></pre>
<p>Can become:</p>
<pre><code>for (NSDictionary *item in items) @autoreleasepool {
    // lots of stuff here
}
</code></pre>
<p>Now, always making C statements compound in a condition or loop is a pretty common convention. And if you stick by this convention in other places (as I do), that’s fine. But the reasoning behind it doesn’t really apply with <code>@autoreleasepool</code> and <code>@synchronized</code>: you can just consider them part of the opening bracket.</p>
<p>Unfortunately, you can’t do this at the top level of message handlers. Wouldn’t that be nice?</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>Restart Xcode now</title>
      <link>https://tewha.net/2012/08/restart-xcode-now/</link>
      <pubDate>Fri, 03 Aug 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/08/restart-xcode-now/</guid>
      <description>&lt;p&gt;If you’re a heavy user of Xcode, you’ve probably had it go sideways on you. Thankfully, the crashes that plagued previous versions are mostly gone. But in its place are some awkward debugger connection failures, long delays and such.&lt;/p&gt;
&lt;p&gt;Here’s how I created a shortcut key to relaunch Xcode.&lt;/p&gt;
&lt;p&gt;You may find &lt;a href=&#34;https://github.com/boredzo/programmers-killswitch&#34;&gt;Programmer’s KillSwitch&lt;/a&gt; more practical, but this is a fun exercise in using Automator.&lt;/p&gt;
&lt;p&gt;Ready? Here we go.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>If you’re a heavy user of Xcode, you’ve probably had it go sideways on you. Thankfully, the crashes that plagued previous versions are mostly gone. But in its place are some awkward debugger connection failures, long delays and such.</p>
<p>Here’s how I created a shortcut key to relaunch Xcode.</p>
<p>You may find <a href="https://github.com/boredzo/programmers-killswitch">Programmer’s KillSwitch</a> more practical, but this is a fun exercise in using Automator.</p>
<p>Ready? Here we go.</p>
<h2 id="automator">Automator</h2>
<p>Mac OS X includes a service called Automator, that can be used to build workflows. These are like AppleScripts, but less like code and more like macros.</p>
<p>Start with an Application workflow, and drag a Shell Script action to it. Use this code:</p>
<pre><code>pkill -9 -x Xcode
sleep 0.3
</code></pre>
<p>Depending on how fast your Mac is, you may need to increase the sleep value. If Xcode doesn’t always return, increase it.</p>
<p>Next, drag a Launch Application action. Pick Xcode.</p>
<p><img src="https://github.com/images/Relaunch-Xcode.png" alt="Relaunch Workflow"></p>
<p><em>In this workflow, I also remove the DerivedData directory.</em></p>
<p>Save, and you have an application you can run at any time to kill and relaunch Xcode.</p>
<p>This is a great start, but now let’s make it even easier.</p>
<h2 id="fastscripts">FastScripts</h2>
<p>Red Sweater Software has a great utility we can use called <a href="http://www.red-sweater.com/fastscripts/">FastScripts</a>. FastScripts adds a menu to the right of the menu bar, and can launch scripts and other useful things from selecting them in the menu or a keyboard shortcut.</p>
<p>Copy the application you built to FastScript’s folder, then set it to a keyboard command shortcut. I use command-control-delete, which feels like ctrl-alt-del. Very satisfying to hit ctrl-alt-del whenever Xcode starts to act up!</p>
<h2 id="other_possibilities">Other possibilities</h2>
<p>This combination of shell scripting + FastScripts is great for frequent but annoying tasks. I have shell scripts to <code>purge</code> cached memory, and another Xcode restart workflow that clears Xcode’s derived data.</p>
<p>With a few scripts and keyboard shortcuts, you can make Xcode bow to your whim, rather than the other way around.</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>Make a symbolic link from Finder</title>
      <link>https://tewha.net/2012/07/make-a-symbolic-link-from-finder/</link>
      <pubDate>Sat, 28 Jul 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/07/make-a-symbolic-link-from-finder/</guid>
      <description>&lt;p&gt;In a previous entry, I explained &lt;a href=&#34;https://tewha.net/2012/07/how-to-sync-xcode-4s-key-bindings-and-code-snippets/&#34;&gt;How to Sync Xcode’s Settings&lt;/a&gt; via &lt;a href=&#34;http://db.tt/ht6NoXF8&#34;&gt;Dropbox&lt;/a&gt;. This involves creating symlinks in Terminal, and cleverly moving files about.&lt;/p&gt;
&lt;p&gt;You can’t create symlinks in Finder with what Apple provides you, but you &lt;strong&gt;can&lt;/strong&gt; create an Automator workflow to do so easily.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In a previous entry, I explained <a href="/2012/07/how-to-sync-xcode-4s-key-bindings-and-code-snippets/">How to Sync Xcode’s Settings</a> via <a href="http://db.tt/ht6NoXF8">Dropbox</a>. This involves creating symlinks in Terminal, and cleverly moving files about.</p>
<p>You can’t create symlinks in Finder with what Apple provides you, but you <strong>can</strong> create an Automator workflow to do so easily.</p>
<ol>
<li>Create a new service in Automator.</li>
<li>Select: Service receives <strong>selected files or folders</strong> in <strong>any application</strong>.</li>
<li>Drag a Run Shell Script action.</li>
<li>Shell: <strong>/bin/bash</strong> (Even if you’re using another shell as your default shell, this script is for bash.)</li>
<li>Pass input: <strong>as arguments</strong>.</li>
<li>Use this script:</li>
</ol>






<pre tabindex="0"><code>while [ $# -ne 0 ]; do
     ln -s &#34;$1&#34; &#34;$1 symlink&#34;
     shift
 done</code></pre>
<ol start="7">
<li>The result should look like this:<br>
<img src="/images/Make-Symlink-Workflow.png" alt="Dropbox Workflow"></li>
</ol>
<p>Alternately, you can <a href="http://dl.dropbox.com/u/1606770/Goodies/Make%20SymLink.workflow.zip">download my finished service</a> from Dropbox. It should be stored in <strong>~/Library/Services</strong>.</p>
<p>You should now have a Make SymLink command when you right- or control-click a file or folder in the Finder:</p>
<p><img src="/images/Make-Symlink-Menu.png" alt="Make SymLink menu command"></p>
<p>You can even add a keyboard shortcut for it in System Preferences:</p>
<p><img src="/images/Make-Symlink-Shortcut.png" alt="Services Shortcut Key"></p>
<p><em>Remember:</em> A symlink does not follow the original file if the original file moves on your hard drive.</p>]]></content:encoded>
    </item>
    <item>
      <title>How to sync Xcode 4’s key bindings and code snippets</title>
      <link>https://tewha.net/2012/07/how-to-sync-xcode-4s-key-bindings-and-code-snippets/</link>
      <pubDate>Wed, 18 Jul 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/07/how-to-sync-xcode-4s-key-bindings-and-code-snippets/</guid>
      <description>&lt;p&gt;You can use Dropbox to synchronize Xcode 4’s key bindings, code snippets, named tabs, and font &amp;amp; color schemes. If you don’t have a Dropbox account yet, &lt;a href=&#34;http://db.tt/ht6NoXF8&#34;&gt;you can sign up here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The secret is &lt;em&gt;symlinks&lt;/em&gt;. These are different from the aliases you can create in Finder, so you’ll need to do this in the shell.&lt;/p&gt;
&lt;p&gt;The problem with this is that Xcode 4 will not follow symlinks. Luckily, Dropbox will. (Note, however, that Dropbox will &lt;strong&gt;not&lt;/strong&gt; follow aliases.)&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>You can use Dropbox to synchronize Xcode 4’s key bindings, code snippets, named tabs, and font &amp; color schemes. If you don’t have a Dropbox account yet, <a href="http://db.tt/ht6NoXF8">you can sign up here</a>.</p>
<p>The secret is <em>symlinks</em>. These are different from the aliases you can create in Finder, so you’ll need to do this in the shell.</p>
<p>The problem with this is that Xcode 4 will not follow symlinks. Luckily, Dropbox will. (Note, however, that Dropbox will <strong>not</strong> follow aliases.)</p>
<p>On your first computer:</p>
<ol>
<li>Quit Xcode.</li>
<li>Create a directory for your sync on Dropbox. I use <code>~/Dropbox/Sync</code>. In it, I have a subdirectory for Xcode.</li>
<li>Move Xcode’s UserData directory to your Dropbox:<br>
<code>mv ~/Library/Developer/Xcode/UserData ~/Dropbox/Sync/Xcode/UserData</code></li>
<li>Let Dropbox upload everything.</li>
<li>Pause Dropbox’s syncing.</li>
<li>Move them back to where Xcode stores them:<br>
<code>mv ~/Dropbox/Sync/Xcode/UserData ~/Library/Developer/Xcode/UserData</code></li>
<li>Create a symbolic link from your UserData to DropBox:<br>
<code>ln -s ~/Library/Developer/Xcode/UserData ~/Dropbox/Sync/Xcode/UserData</code></li>
<li>Resume Dropbox syncing.</li>
<li>Relaunch Xcode.</li>
</ol>
<p>On any other computer:</p>
<ol>
<li>Quit Xcode.</li>
<li>Let Dropbox download everything, if it hasn’t yet.</li>
<li>Pause Dropbox syncing.</li>
<li>Remove your local Xcode user data:<br>
<code>rm -R ~/Library/Developer/Xcode/UserData</code></li>
<li>Move your UserData from Dropbox to Xcode:<br>
<code>mv ~/Dropbox/Sync/Xcode/UserData ~/Library/Developer/Xcode/UserData</code></li>
<li>Create a symbolic link from your UserData to DropBox:<br>
<code>ln -s ~/Library/Developer/Xcode/UserData ~/Dropbox/Sync/Xcode/UserData</code></li>
<li>Resume Dropbox syncing.</li>
<li>Relaunch Xcode.</li>
</ol>
<p>You can also synchronize your Archives directory, using the same technique.</p>
<p>This technique is not perfect, as Xcode will probably not recognize changes while running. However, it is better than having to manually copy these directories between computers.</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>Use a Build Phase to validate XML</title>
      <link>https://tewha.net/2012/04/use-a-build-phase-to-validate-xml/</link>
      <pubDate>Tue, 17 Apr 2012 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/04/use-a-build-phase-to-validate-xml/</guid>
      <description>&lt;p&gt;My application includes some XML files that are used while running to map data from a web service. This has drastically simplified the code I needed to write to parse data from the web service, since I can describe how to decode all of the types of object the web service interacts with simply.&lt;/p&gt;
&lt;p&gt;If I accidentally provide bad XML, I don’t know until my app tries to parse it. That may be some time into its run. If the XML is processed because of a specific user action, I’ve broken that specific user action. So we’re going to build a build phase to validate the XML.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>My application includes some XML files that are used while running to map data from a web service. This has drastically simplified the code I needed to write to parse data from the web service, since I can describe how to decode all of the types of object the web service interacts with simply.</p>
<p>If I accidentally provide bad XML, I don’t know until my app tries to parse it. That may be some time into its run. If the XML is processed because of a specific user action, I’ve broken that specific user action. So we’re going to build a build phase to validate the XML.</p>
<p>Obviously, I want to test everything in my app before I post it to the iTunes Store. But finding this problem even <em>hours</em> later makes it harder to diagnose and fix. I can detect this error immediately (and fix it right away) by adding a build phase to validate my XML.</p>
<p>I added a run script to my target that does this:</p>
<pre><code>find &quot;${PROJECT_DIR}&quot; -name *.xml -exec xmllint {} ;
</code></pre>
<p><em>See update below.</em></p>
<p><img src="/images/Validation-Phase.png" alt="Validation Build Phase"></p>
<p>Xcode will run this script when building my target. It will find all XML files in my project directory, and run <code>xmllint</code> on them. <code>xmllint</code> returns an error if the document is malformed.</p>
<p>I gave this build phase a good name so I can find it easily later, then dragged the script as high in my build phase order as possible to get the results early. This may not actually prevent the project from building, but at least I get a big red error.</p>
<p>This validates <strong>all</strong> the XML in my project directory. If you have XML you don’t need, you’ll have to do something more complicated:</p>
<ul>
<li>Provide a more specific starting path</li>
<li>Use one of the other variables validate the built .app package instead, or</li>
<li>Hard code each XML file’s path</li>
</ul>
<h2 id="update">Update</h2>
<p>This command works better:</p>
<pre><code>find &quot;${PROJECT_DIR}&quot; -name *.xml -print0 | xargs -n 1 -0 xmllint
</code></pre>
<p>With this command, the error not only stops Xcode, but Xcode highlights the line that xmllint reports as the offender.</p>]]></content:encoded>
    </item>
    <item>
      <title>Creativity is not a product of thinking</title>
      <link>https://tewha.net/2012/02/creativity-is-not-a-product-of-thinking/</link>
      <pubDate>Sat, 04 Feb 2012 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/02/creativity-is-not-a-product-of-thinking/</guid>
      <description>&lt;p&gt;Who I am is the sum of many parts. More than my mind wants me to believe. There’s a part of me that’s capable of problem solving, of creativity, of insight.&lt;/p&gt;
&lt;p&gt;My mind is the part of me that questions things. It’s my inner critic. It does most of the talking in my head. Mostly, it tells me that I can’t do something. &lt;em&gt;This is hard. That’s wrong. You’ve got nothing new to add to this.&lt;/em&gt; This is not how I solve problems, though it drives me to find better solutions to problems.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Who I am is the sum of many parts. More than my mind wants me to believe. There’s a part of me that’s capable of problem solving, of creativity, of insight.</p>
<p>My mind is the part of me that questions things. It’s my inner critic. It does most of the talking in my head. Mostly, it tells me that I can’t do something. <em>This is hard. That’s wrong. You’ve got nothing new to add to this.</em> This is not how I solve problems, though it drives me to find better solutions to problems.</p>
<p>My eyes speak to me, too. <em>This is ugly. How can you keep writing when the font is wrong? There’s a spelling error, go fix it!</em> This is not how I solve problems, though it’s how I see that problems exist.</p>
<p>My creativity flows from something else, the most quiet part of me. It’s actually what I’m using right now to write this. It’s my fingers. It’s not actually my fingers, of course, but it’s the part of my brain that sets my fingers in motion, across a keyboard or across an open page. It’s the part of my brain that, when my mind said I had nothing worthwhile to type today, started typing before deciding what to type. It’s the part of me that tries to draw a face, and doesn’t care that the face looks like something an untalented preschool child might draw. It’s the part of me that produced the first draft of this, spelling errors and crappy fonts and occasional run-on sentence and all.</p>
<p>This is the part of me that I’ve been poor at nurturing in 2011. The part of me that’s been broken. The part of me that my mind has held tightly, that the tiny animal in me has said is worthless.</p>
<p>My mind wants me to stop writing this post, because it has no value. That’s its job, to question things. But when it questions not just my output, but that I am <em>creating</em> at all, it needs to be ignored.</p>
<p>My eyes want me to go change the font so I’m no longer typing in Cochin 17. (Really, Cochin 17? What kind of default is that?) That’s it’s job, to make things beautiful once problems are recognized. But when it wants me to waste time on appearance instead of typing, it needs to be ignored.</p>
<p>Until the words have flowed from my fingers, there must be nothing but my fingers. This is my pledge to myself for the year; to create first, to criticize my creations after they are created rather than before.</p>
<p>My fingers know what they’re doing, and they’re the best part of me.</p>]]></content:encoded>
    </item>
    <item>
      <title>I’ve changed my mind about Xcode snapshots</title>
      <link>https://tewha.net/2012/01/ive-changed-my-mind-about-xcode-snapshots/</link>
      <pubDate>Fri, 27 Jan 2012 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2012/01/ive-changed-my-mind-about-xcode-snapshots/</guid>
      <description>&lt;p&gt;In the recent past, &lt;a href=&#34;https://tewha.net/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots&#34;&gt;I’ve mocked Xcode’s snapshots&lt;/a&gt;. They were sluggish and not especially reliable. I’d like to say they were inefficient, too, but the truth is that they were so slow and so unreliable I never bothered to find out.&lt;/p&gt;
&lt;p&gt;Recent versions of Xcode have been a lot better. I’m not sure when archives really improved, but in the most recent build of Xcode archive takes only a split second. So far, they seem reliable. And they work by storing the source in a private &lt;code&gt;git&lt;/code&gt; repository, so they’re pretty efficient, too. This does &lt;strong&gt;not&lt;/strong&gt; affect your real &lt;code&gt;git&lt;/code&gt; repository, even if you’re using &lt;code&gt;git&lt;/code&gt;. This is entirely separate, deep in Xcode’s private directory tree deep in your home folder.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In the recent past, <a href="/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots">I’ve mocked Xcode’s snapshots</a>. They were sluggish and not especially reliable. I’d like to say they were inefficient, too, but the truth is that they were so slow and so unreliable I never bothered to find out.</p>
<p>Recent versions of Xcode have been a lot better. I’m not sure when archives really improved, but in the most recent build of Xcode archive takes only a split second. So far, they seem reliable. And they work by storing the source in a private <code>git</code> repository, so they’re pretty efficient, too. This does <strong>not</strong> affect your real <code>git</code> repository, even if you’re using <code>git</code>. This is entirely separate, deep in Xcode’s private directory tree deep in your home folder.</p>
<p>Xcode can run a behaviour when a build succeeds. You can customize the behaviour in Xcode’s Preferences. I noticed a few days ago that there’s also an option to <strong>Create snapshot</strong>.</p>
<p><img src="/images/Create-snapshot.png" alt="Create snapshot"></p>
<p>You may need to scroll down to see the <strong>Create snapshot</strong> option.</p>
<p>This means that every time my project builds successfully, a snapshot is created. The snapshots are small, basically containing only the changes since the last build. I expect I can leave this on basically forever without running out of disk space.</p>
<p>I commit to <code>git</code> many times during the course of the day, but occasionally I’ll be in a refactor and I won’t be committing every time the project builds. I’ll make a few changes, build and fix any errors, make a few more changes. I’ll keep this up several times, until I’ve made the full refactor I want. Only then will I fully test what I’ve done and commit.</p>
<p>Sometimes I’ll make the wrong change, and break the build in ways I can’t easily fix. At that point, I either need to struggle my way out of the errors I’ve introduced or abandon all the changes I’ve made. Yes, I could commit to <code>git</code> every time. But the smaller each individual change is, the less likely I am to bother.</p>
<p>In my defence, I still think the way Xcode uses snapshots by default is useless. They’re offered before major but atomic changes, which is right after I’ve committed to my source control repository manually.</p>
<p>But these continuous snapshots are another matter. This means I can back out of any particular change back to the previous working code without losing all the changes so far in what I consider the full, atomic refactor.</p>
<p>I’m thrilled this feature exists, and I’ll be using it from now on. I think you should give it a try, too. Even if you commit to your source control system constantly, this will make commits you won’t think to, and without any action on your part.</p>]]></content:encoded>
    </item>
    <item>
      <title>How the iPhone GPS differs from a standalone navigation GPS</title>
      <link>https://tewha.net/2011/10/how-the-iphone-gps-differs-from-a-standalone-navigation-gps/</link>
      <pubDate>Sat, 29 Oct 2011 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2011/10/how-the-iphone-gps-differs-from-a-standalone-navigation-gps/</guid>
      <description>&lt;p&gt;All models of iPhone since the 3G, as well as the iPad 3G and iPad 2 3G, include Assisted GPS (AGPS).&lt;/p&gt;
&lt;p&gt;I’ve heard that this isn’t real GPS or that it’s somehow inferior to real GPS. AGPS is actually superior to “real” GPS. However, there are ways the iPhone is also inferior to a standalone navigational GPS like a Garmin or Tom Tom. I’m going to explain the differences between them.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>All models of iPhone since the 3G, as well as the iPad 3G and iPad 2 3G, include Assisted GPS (AGPS).</p>
<p>I’ve heard that this isn’t real GPS or that it’s somehow inferior to real GPS. AGPS is actually superior to “real” GPS. However, there are ways the iPhone is also inferior to a standalone navigational GPS like a Garmin or Tom Tom. I’m going to explain the differences between them.</p>
<h2 id="positioning">Positioning</h2>
<p>The iPhone includes a regular GPS receiver, just like your standalone GPS. The “assisted” part means the iPhone is able to get a quick lock based on other data sources, such as nearby cell phone towers or WiFi networks.</p>
<p>I’m not going to try to write an explanation of this. There’s a great article on this in Macworld by Glenn Fleishman, ”<a href="https://www.macworld.com/article/159528/2011/04/how_iphone_location_works.html">How the iPhone knows where you are</a>,” which you should read. He’s a journalist who specializes in wireless technologies, and anything I could write on that subject would fail to measure up to his writing.</p>
<p>But I can summarize that article for you in one paragraph, if you didn’t bother to read it:</p>
<p>Because the iPhone has a GPS radio <em>and</em> these other data sources, it’s quicker at finding your location than a standalone navigational GPS.</p>
<p>Your iPhone does this without sacrificing final accuracy, but may give you several approximations along the way. (These are times a real GPS would still be trying to figure out where you are.) This is simplifying a little; the iPhone needs to conserve battery more than your standalone GPS. If you’re not actually using Maps or some other application that needs pinpoint accuracy, it probably powers down the GPS and uses whatever radios it has powered up to do approximate positioning rather than the most accurate positioning it’s capable of. But when you need accurate positioning, it’s there.</p>
<h2 id="maps">Maps</h2>
<p>So why do people think the iPhone’s GPS isn’t a real GPS? It’s because of the one way the iPhone is weaker than your standalone GPS. As shipped by Apple, the iPhone is completely dependent on the Internet for map tile data.</p>
<p>That means that without a data signal, whether WiFi or 3G, the iPhone is unable to show you a map. You end up with a screen like this:</p>
<p><img src="https://www.macworld.com/images/No-Maps.png" alt="No Maps"></p>
<p>From this, you might conclude that without a data connection your iPhone isn’t very good as a navigational tool. You’d be right about that! But you might also conclude that the iPhone doesn’t know where you are. In fact, it knows where you are. It just isn’t able to put it on a map, because it doesn’t actually have a map of the area.</p>
<p>This is where standalone GPS devices are better. Because they don’t have the extra radios that the iPhone has, they can’t download map data from the Internet. Instead, a standalone GPS includes map data on the device. Storing an entire country’s (or even an entire continent’s) map data takes a lot of space, so it’s often rendered more crudely than the iPhone’s maps.</p>
<p>Imagine drawing a map for a friend to get to your house. You know which road they’ll be coming on, and you know where they’re trying to go. You can fill in the roads they need to pay attention to from memory, and mark turns and the destination. This is how a standalone GPS works, except that if it’s up-to-date it knows <strong>all</strong> the roads and can quickly draw everything quickly and to scale. It’s rendered using just its memory, without the aid of a 3G or WiFi network.</p>
<p>The iPhone’s maps, on the other hand, are from the cloud. The iPhone basically asks for a graphical map from the cloud, with the location and zoom it’s interested in. The image the cloud returns can be beautifully rendered and completely up-to-date, but without the cloud, the iPhone can’t get anything.</p>
<p>But what if your iPhone did have map data on device? Then it would be able to render maps without a data connection AND get a fix faster than a real standalone GPS. This is where the App Store comes in to play. Tom Tom and Garmin both sell apps that include map data. When running one of these apps, the iPhone is able to find its location faster than a standalone GPS. However, even without a connection to the Internet, the app is able to provide a map.</p>
<h2 id="turnbyturn_navigation">Turn-by-turn navigation</h2>
<p>If you’ve reached this point, you’re probably wondering why the iPhone can’t do turn-by-turn navigation. It’s a fair question. The answer is complicated, but boils down simply: Apple does not provide the map data. Instead, Apple’s map display uses data provided by Google. And Google does not allow Apple to use that map data for turn-by-turn navigation. Apple, in turn, does not allow iPhone developers to submit turn-by-turn navigation apps that use the iPhone’s map system.</p>
<p>So why can some Android phones provide turn-by-turn navigation? Google allows it.</p>
<p>This is why any turn-by-turn navigation app is going to require its own map data, rather than working off the cloud when it’s available. There’s been a few hints that Apple may switch to their own data at some point, but it hasn’t happened yet. Being dependent on a competitor interested in keeping your device inferior isn’t a good position to be in, even if the reasoning has nothing to do with competition.</p>
<p><strong>Update:</strong> The next version of iOS 6 will switch the data source to Apple’s. The iPhone will still download map data, but instead of downloading just a picture it will now download richer data that will allow it to display rotated maps more cleanly. And Apple is bringing turn-by-turn directions to the iPhone 4S. The iPhone will not get offline navigational data, however.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The iPhone’s GPS us very good. Without extra software, however, iPhone <strong>navigation</strong> is entirely dependent on the Internet. But you can see maps as long as the iPhone can reach the cloud. You can download software so you can see maps while away from the cloud. And any photo you take, even while away from the cloud, will still be tagged with the location of the iPhone.</p>
<p>The iPhone makes its connection to the cloud a strength, whereas standalone GPS units have made the lack of a radio their strength. It’s a complicated tradeoff. Saying the iPhone does not have “real” GPS or that AGPS is not “real”, though, is inaccurate.</p>]]></content:encoded>
    </item>
    <item>
      <title>Dennis Ritchie</title>
      <link>https://tewha.net/2011/10/dennis-ritchie/</link>
      <pubDate>Thu, 13 Oct 2011 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2011/10/dennis-ritchie/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://herbsutter.com/2011/10/12/dennis-ritchie/&#34;&gt;Dennis Ritchie&lt;/a&gt;, creator of the C programming language, has died at age 70.&lt;/p&gt;
&lt;p&gt;This soon after my post on Steve Jobs, I’m unable to write much on the subject. But the C programming language was a major invention in the history of computers, and a significant step in the evolution of computers from academia and processing centres to programs for the real world.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><a href="http://herbsutter.com/2011/10/12/dennis-ritchie/">Dennis Ritchie</a>, creator of the C programming language, has died at age 70.</p>
<p>This soon after my post on Steve Jobs, I’m unable to write much on the subject. But the C programming language was a major invention in the history of computers, and a significant step in the evolution of computers from academia and processing centres to programs for the real world.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Steve Jobs shaped my life</title>
      <link>https://tewha.net/2011/10/steve-jobs-shaped-my-life/</link>
      <pubDate>Thu, 06 Oct 2011 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2011/10/steve-jobs-shaped-my-life/</guid>
      <description>&lt;p&gt;I never met Steve Jobs. I’ve never even been in the same room as him, or (to my knowledge), the same city.&lt;/p&gt;
&lt;p&gt;So why am I choked up about his death? Because I love the man for what he accomplished, and how he’s changed the world.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I never met Steve Jobs. I’ve never even been in the same room as him, or (to my knowledge), the same city.</p>
<p>So why am I choked up about his death? Because I love the man for what he accomplished, and how he’s changed the world.</p>
<p>Way back in elementary school, I used an Apple //e. I moved Logo’s turtle around on the screen. I discovered something odd: being able to understand that computers were predictable machines, rather than mysteries had separated me. There are an infinite number of things others can do better than I. Other kids could run, they could play team sports and not let down their team. But this, I could do. But what use was it? Computers were only good at being computers. FORWARD 10. RIGHT 45. Repeat 8 times, it was a stop sign.</p>
<p>I learned BASIC and Pascal, but on some level I was still drawing stop signs. I was solving problems no one had.</p>
<p>Around age nine or ten, I was at a school looking at various displays. Most were uninteresting. But there was an original beige Macintosh, running MacPaint.</p>
<p>The Macintosh was something else entirely. That was something useful. I had only a few minutes with it. I moved the mouse about, watching the cursor. I clicked a few things; I think I doodled a bit with the pencil, typed some text, and used the eraser. It made sense to me. More than that, it dawned on me that computers could be things other than a computer. The complexity behind it was boggling, but someone had solved it. Therefore, it was solvable. It wasn’t actually magic, it just felt like it. I didn’t know it at the time, but Steve Jobs had made that experience happen. He didn’t write the code, and exactly how much of the design was his I’ll never know. Many talented individuals had brought that experience into being. But he drove the team, and he pushed the vision.</p>
<p>It would be several more years before my next encounter with the Macintosh, but something had changed for me. I knew a bit about programming already, but now I wanted to solve real problems for real people.</p>
<p>I practiced for years, and I impressed some people, and ended up with a job programming computers. And I enjoyed that job, and I enjoyed what we were building, but it wasn’t what I yearned to build. It wasn’t accessible to enough people. It was still hard-to-hit buttons, activated by sliding a cursor around the screen using a plastic box.</p>
<p>It turns out that computers, even the Macintosh, were too complex. It was tough to master the indirectness of the interface. For a time, I smugly assumed I was smarter than the people who couldn’t get this, but that wasn’t the case at all. If anything, just the opposite: these machines were far more hostile than I was willing to admit. I couldn’t see the problems in front of me.</p>
<p>There was Palm. They made a hesitant half-step in the right direction, but it didn’t last. I knew we were going backwards again, but I didn’t know how or why.</p>
<p>Years passed. And finally, the iPhone. In the iPhone, you could see at last the future, what Apple intended for the next generation. Even if it was just a small, 3.5” cut of it. Again, that was Steve Jobs. Not solely responsible. I don’t even know that it was his idea. But either way, he owned that idea. He nurtured it, he cultured it, and he grew it. He turned complex computers and crappy phones into something entirely new.</p>
<p>But I think you could also see echoes of the past: What Apple had wanted to produce with the Macintosh, but been unable to.</p>
<p>A few years later, we got a bigger slice of the future with the iPad. The iPad does not represent <strong>finished</strong> by any means, but I believe it is the realization of what Apple truly had in mind with the original Macintosh, and an extension of what they tried to achieve with the iPhone. It’s more than a computer — so much immeasurably more — by being less than a computer. And, again, Steve Jobs was responsible. Not solely, of course. But in the same sense that had it gone wrong, one person would be to blame, if one person must be given credit that person is Steve Jobs.</p>
<p>And along they way, he reinvented the music industry. And he’d have reinvented both television and movies for the better, too, had the existing powers in those industries been more eager to follow.</p>
<p>Through demonstration, Steve Jobs had taught me a few things:</p>
<ul>
<li>Great products are worth using, so they’re worth building.</li>
<li>Great things can achieved, even under pressure from others who don’t see the same future.</li>
<li>Greatness is revolutionary, but does not ignore what’s gone before.</li>
<li>It’s okay to not achieve perfection. Producing something amazing is good enough.</li>
<li>Having achieved something amazing, there’s something <strong>more</strong> amazing just ahead.</li>
<li>True greatness means the result is not just easy to use, but unbelievable easy. Magical, even.</li>
</ul>
<p>There are thousands of developers in the world who’ve learned these same lessons. Many of them learned before me. Some of them learned from different sources. But the entire industry has been influenced by the revolutionary evolution of computing from Apple and Steve Jobs. We make up a small part of his legacy. Part of our job is to use these lessons to build magic. The greater part is to inspire others to build magic.</p>
<p>Thank you, Mr. Jobs. Tomorrow, the temptation will be to say the sun rises on a world with less magic. But that’s only true if we don’t create more of our own.</p>]]></content:encoded>
    </item>
    <item>
      <title>An imaginary conversation with Xcode 4 regarding snapshots</title>
      <link>https://tewha.net/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots/</link>
      <pubDate>Fri, 09 Sep 2011 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots/</guid>
      <description>&lt;p&gt;Me: Yeah?&lt;/p&gt;
&lt;p&gt;Xcode: You want to enable snapshots yet?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Me: Yeah?</p>
<p>Xcode: You want to enable snapshots yet?</p>
<p>Me: No.</p>
<p>Xcode: I’m just asking.</p>
<p>Me: No.</p>
<p>Xcode: They’re good for you, you know.</p>
<p>Me: I’m sure they are, but see, I’ve already backed up my project. In fact, I checked it all into source control. You were there, right?</p>
<p>Xcode: Yeah, but can I enable snapshots? Please?</p>
<p>Me: No. Stop asking.</p>
<p>Xcode: I’ve caught you at a bad time.</p>
<p>Me: That’s not it. I don’t actually <strong>want</strong> snapshots. They’re redundant, and frankly a bit stupid. It makes me feel like you don’t respect me enough to make my own backups, you know?</p>
<p>Xcode: Oh. I can see that. I’ll ask again later, then.</p>]]></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>
    <item>
      <title>How to reset Wii to lower resolution</title>
      <link>https://tewha.net/2011/08/how-to-reset-wii-to-lower-resolution/</link>
      <pubDate>Sun, 07 Aug 2011 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2011/08/how-to-reset-wii-to-lower-resolution/</guid>
      <description>&lt;p&gt;So you’ve set your Wii to 480p, then moved it back to a TV that supports only 480i. How do you fix it?&lt;/p&gt;
&lt;p&gt;I searched for this for a while and found a few wrong and complicated answers.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>So you’ve set your Wii to 480p, then moved it back to a TV that supports only 480i. How do you fix it?</p>
<p>I searched for this for a while and found a few wrong and complicated answers.</p>
<p>One way is to use the composite cable instead of the component cable. Your Wii came with a composite cable, and if you’re only using 480i the component cable does nothing extra for you anyway.</p>
<p>But what if you can’t find the composite cable? This was the case for me, after my move. The answer is ridiculously simple:</p>
<ol>
<li>Unplug the component cable on the Wii end.</li>
<li>If the Wii is already on, press the Reset button. If it was off, turn it on.</li>
<li>Wait a couple seconds. The Wii will notice there’s no component cable plugged in, and switch to 480i mode.</li>
<li>Plug the component cable back into the Wii.</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Blocks to remove redundancy</title>
      <link>https://tewha.net/2011/07/blocks-to-remove-redundancy/</link>
      <pubDate>Fri, 29 Jul 2011 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2011/07/blocks-to-remove-redundancy/</guid>
      <description>&lt;p&gt;Blocks have many complicated uses, from event-based code to multithreading. But they can also be used for very trivial tasks, such as removing redundant lines from code.&lt;/p&gt;
&lt;p&gt;Here’s a common operation for me: Split a list into sublists based on some piece of data changing within a loop. When the loop is over, dump whatever’s left into another sublist.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Blocks have many complicated uses, from event-based code to multithreading. But they can also be used for very trivial tasks, such as removing redundant lines from code.</p>
<p>Here’s a common operation for me: Split a list into sublists based on some piece of data changing within a loop. When the loop is over, dump whatever’s left into another sublist.</p>
<p>Without blocks, this looks like this:</p>
<pre><code>- (NSArray *)splitArray: (NSArray *)array
               valueKey: (NSString *)valueKey
               labelKey: (NSString *)labelKey;
{
    id sections = [NSMutableArray array];
    id sectionValue = nil;
    id sectionRecords = [NSMutableArray array];
    
    for (id record in array) {
        id recordValue = [record objectForKey: valueKey];
        if ( ![recordValue isEqual: sectionValue] ) {
            if ( [sectionRecords count] ) {
                id lastRecord = [sectionRecords objectAtIndex: 0];
                id label = [lastRecord objectForKey: labelKey];
                id section = [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSArray arrayWithArray: sectionRecords], @&quot;Records&quot;,
                              label, @&quot;Name&quot;,
                              nil];
                [sections addObject: section];
                [sectionRecords removeAllObjects];
            }
            sectionValue = recordValue;
        }
        [sectionRecords addObject: record];
    }
    if ( [sectionRecords count] ) {
        id lastRecord = [sectionRecords objectAtIndex: 0];
        id label = [lastRecord objectForKey: labelKey];
        id section = [NSDictionary dictionaryWithObjectsAndKeys:
                      [NSArray arrayWithArray: sectionRecords], @&quot;Records&quot;,
                      label, @&quot;Name&quot;,
                      nil];
        [sections addObject: section];
        [sectionRecords removeAllObjects];
    }
    
    return [NSArray arrayWithArray: sections];
}
</code></pre>
<p>The redundancy makes this hard to maintain, but I don’t really want to split it off into a different function. That means passing all the parameters in to the second function.</p>
<p>But wait! Can we use blocks to clean this up? Yes, we can! We can define the code we want to execute in a block, then use the block as necessary within the function.</p>
<p>With blocks, the code looks like this:</p>
<pre><code>- (NSArray *)splitArray: (NSArray *)array
               valueKey: (NSString *)valueKey
               labelKey: (NSString *)labelKey;
{
    id sections = [NSMutableArray array];
    id sectionValue = nil;
    id sectionRecords = [NSMutableArray array];
    
    dispatch_block_t split = ^{
        if ( [sectionRecords count] ) {
            id lastRecord = [sectionRecords objectAtIndex: 0];
            id label = [lastRecord objectForKey: labelKey];
            id section = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSArray arrayWithArray: sectionRecords], @&quot;Records&quot;,
                          label, @&quot;Name&quot;,
                          nil];
            [sections addObject: section];
            [sectionRecords removeAllObjects];
        }
    };
    
    for (id record in array) {
        id recordValue = [record objectForKey: valueKey];
        if ( ![recordValue isEqual: sectionValue] ) {
            split();
            sectionValue = recordValue;
        }
        [sectionRecords addObject: record];
    }
    split();
    
    return [NSArray arrayWithArray: sections];
}
</code></pre>
<p>Since the block by default has read-only access to any variable it wants as long as it’s in scope, there’s no need to pass parameters into the block.</p>
<p>As I said in the introduction, blocks are a lot more powerful than this. See Apple’s <a href="http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/Blocks">Block Programming Topics</a> for more about that. However, they’re a great tool for small problems as well that you shouldn’t overlook.</p>]]></content:encoded>
    </item>
    <item>
      <title>Flux adjusts your monitor’s color temperature</title>
      <link>https://tewha.net/2010/12/flux-adjusts-your-monitors-color-temperature/</link>
      <pubDate>Sat, 04 Dec 2010 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2010/12/flux-adjusts-your-monitors-color-temperature/</guid>
      <description>&lt;p&gt;Install &lt;a href=&#34;http://www.stereopsis.com/flux&#34;&gt;Flux&lt;/a&gt; right now.&lt;/p&gt;
&lt;p&gt;What does it do? Well, at sunset it adjusts the color temperature of your monitor to make it warmer and less glaring. At sunrise, it adjusts it back.&lt;/p&gt;
&lt;p&gt;I installed it yesterday afternoon; yesterday and today at sunset, it automatically adjusted my monitor’s color temperature. The difference on the eyes is nothing short of amazing. And if you need to do some accurate color work, it has a menu that lets you turn it off for an hour.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Install <a href="http://www.stereopsis.com/flux">Flux</a> right now.</p>
<p>What does it do? Well, at sunset it adjusts the color temperature of your monitor to make it warmer and less glaring. At sunrise, it adjusts it back.</p>
<p>I installed it yesterday afternoon; yesterday and today at sunset, it automatically adjusted my monitor’s color temperature. The difference on the eyes is nothing short of amazing. And if you need to do some accurate color work, it has a menu that lets you turn it off for an hour.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Xcode tip: Renaming files shared by projects</title>
      <link>https://tewha.net/2010/12/xcode-tip-renaming-files-shared-by-projects/</link>
      <pubDate>Sat, 04 Dec 2010 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2010/12/xcode-tip-renaming-files-shared-by-projects/</guid>
      <description>&lt;p&gt;What if you want to rename a file that’s used in multiple Xcode projects? Well, previously I’d rename the file in one project, then open each project in series and correct broken references. But I discovered today that this is unnecessary. If you open all of your projects first, Xcode will fix the references across &lt;strong&gt;all&lt;/strong&gt; of your open projects as you rename files in &lt;strong&gt;any&lt;/strong&gt; of the projects.&lt;/p&gt;
&lt;p&gt;For all I know, this has always been a feature of Xcode. But I’ve never noticed it before. So for this stunning display of common sense: Well done, Apple!&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>What if you want to rename a file that’s used in multiple Xcode projects? Well, previously I’d rename the file in one project, then open each project in series and correct broken references. But I discovered today that this is unnecessary. If you open all of your projects first, Xcode will fix the references across <strong>all</strong> of your open projects as you rename files in <strong>any</strong> of the projects.</p>
<p>For all I know, this has always been a feature of Xcode. But I’ve never noticed it before. So for this stunning display of common sense: Well done, Apple!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Better Xcode warnings through .xcconfig files</title>
      <link>https://tewha.net/2010/11/better-xcode-warnings-through-xcconfig-files/</link>
      <pubDate>Sat, 27 Nov 2010 16:00:00 +0000</pubDate>
      <guid>https://tewha.net/2010/11/better-xcode-warnings-through-xcconfig-files/</guid>
      <description>&lt;p&gt;Peter Hosey &lt;a href=&#34;http://boredzo.org/blog/archives/2009-11-07/warnings&#34;&gt;posted a list of warnings he turns on&lt;/a&gt;. Here’s the warnings I turn on. It’s mostly the same list.&lt;/p&gt;
&lt;p&gt;Rather than set these per project, I have a .xcconfig file I add to my project. I then base each build configuration off this file. Changing the .xcconfig file changes all projects based on it (though with the current Xcode, it’s sometimes necessary to reload the project to get the settings to take).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Peter Hosey <a href="http://boredzo.org/blog/archives/2009-11-07/warnings">posted a list of warnings he turns on</a>. Here’s the warnings I turn on. It’s mostly the same list.</p>
<p>Rather than set these per project, I have a .xcconfig file I add to my project. I then base each build configuration off this file. Changing the .xcconfig file changes all projects based on it (though with the current Xcode, it’s sometimes necessary to reload the project to get the settings to take).</p>
<p>//
//  MoreWarnings.xcconfig
//
//  Created by Steven Fisher:
//      <a href="http://tewha.net/2010/11/xcode-warnings/">http://tewha.net/2010/11/xcode-warnings/</a>
//  See also:
//      <a href="http://boredzo.org/blog/archives/2009-11-07/warnings">http://boredzo.org/blog/archives/2009-11-07/warnings</a>
//</p>
<pre><code>GCC_WARN_CHECK_SWITCH_STATEMENTS = YES
GCC_WARN_SHADOW = YES
GCC_WARN_64_TO_32_BIT_CONVERSION = YES
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
GCC_WARN_ABOUT_RETURN_TYPE = YES
GCC_WARN_MISSING_PARENTHESES = YES
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
GCC_WARN_ABOUT_MISSING_NEWLINE = YES
GCC_WARN_SIGN_COMPARE = YES
GCC_WARN_UNDECLARED_SELECTOR = YES
GCC_WARN_UNUSED_FUNCTION = YES
GCC_WARN_UNUSED_LABEL = YES
GCC_WARN_UNUSED_VALUE = YES
GCC_WARN_UNUSED_VARIABLE = YES
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES
GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES
GCC_TREAT_WARNINGS_AS_ERRORS = YES
RUN_CLANG_STATIC_ANALYZER = YES
</code></pre>
<p>Peter wrote a great explanation of why you’d want most of these warnings, which I’m not going to attempt. I’ve added some C++ warnings, too. They don’t do anything with clang 1.6, but might be useful in the future.</p>
<p>A few notes:</p>
<ul>
<li>Like Peter, I don’t turn on <code>GCC_WARN_UNUSED_PARAMETER</code>. Although you can add <code>__unused</code> to each parameter to disable the warning, doing so breaks Xcode’s code formatting. I use code formatting constantly, so anything that breaks it isn’t acceptable.</li>
<li>The warnings that were the most painful to turn on were <code>GCC_WARN_64_TO_32_BIT_CONVERSION</code> and <code>GCC_WARN_SIGN_COMPARE</code>. If you use <code>int</code> and <code>NSInteger</code> interchangeably, you’re going to have a tough time with these. (I don’t, but some of the internal libraries I use do.) These are also some of the more dangerous warnings to fix; if you’ve got automated tests, you should run them after every few corrections.</li>
<li><code>RUN_CLANG_STATIC_ANALYZER</code> will roughly double (or more) the time your project takes to compile. I consider this a good trade: I rarely trigger a static analyzer warning now, but when I do I want to fix it.</li>
<li>Also note the <code>GCC_TREAT_WARNINGS_AS_ERRORS</code>. If you are applying these to an existing project, you may start with hundreds of warnings. You’ll probably want to start with this set to <code>NO</code> and change it to <code>YES</code> after you’ve fixed the warnings.</li>
<li>Remember, too, that this changes the <strong>defaults</strong> for settings. You can still specify different settings in the build configuration! If the static analyzer is taking too long to run in one project, just turn it off in that one project but leave the .xcconfig file alone!</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Changing UINavigationBar’s title text color</title>
      <link>https://tewha.net/2010/10/changing-uinavigationbars-title-text-color/</link>
      <pubDate>Fri, 01 Oct 2010 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2010/10/changing-uinavigationbars-title-text-color/</guid>
      <description>&lt;p&gt;How do you change UINavigationBar’s title color? You can’t, directly, but you can substitute your own view.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>How do you change UINavigationBar’s title color? You can’t, directly, but you can substitute your own view.</p>
<p>For example, start with <a href="http://developer.apple.com/library/ios/#samplecode/NavBar/Introduction/Intro.html">Apple’s NavBar sample</a>. Drop this code into <code>initWithNibName:bundle:</code> in <code>PageThreeViewController.m</code>:</p>
<pre><code>- (id)initWithNibName:(NSString *)nibNameOrNil
               bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        // this will appear as the title in the navigation bar
        CGRect frame = CGRectMake(0, 0, 400, 44);
        UILabel *label = [[UILabel alloc] initWithFrame:frame];
        label.backgroundColor = [UIColor clearColor];
        label.font = [UIFont boldSystemFontOfSize:20.0];
        label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
        label.textAlignment = UITextAlignmentCenter;
        label.textColor = [UIColor yellowColor];
        self.navigationItem.titleView = label;
        label.text = NSLocalizedString(@&quot;PageThreeTitle&quot;, @&quot;&quot;);
        [label release];
    }

    return self;
}
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>New iPods and free ponies for all</title>
      <link>https://tewha.net/2010/08/new-ipods-and-free-ponies-for-all/</link>
      <pubDate>Wed, 25 Aug 2010 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2010/08/new-ipods-and-free-ponies-for-all/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://www.macworld.com/article/153661/2010/08/pondering_media_event_2010.html&#34;&gt;Macworld covers&lt;/a&gt; an Apple special event on September 1st. But their predictions hedge bets, offering a “good chance” of something more substantial than just new iPods.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><a href="http://www.macworld.com/article/153661/2010/08/pondering_media_event_2010.html">Macworld covers</a> an Apple special event on September 1st. But their predictions hedge bets, offering a “good chance” of something more substantial than just new iPods.</p>
<p>Well, I’m not famous or Internet famous, so I can go out on a limb and give you a guarantee of what you’ll see. And nobody will care if I’m wrong. So here’s my prediction. Are you ready?</p>
<ul>
<li>New iPods.</li>
<li>An updated iTunes.</li>
<li>That’s it.</li>
</ul>
<p>You will not see an updated Apple TV. You will not see an iPad nano. You will not see The Beatles. You will not see cloud based syncing, unless it’s the only way to sync the new iPod. You will see changes to the iPod, the iPod, the iPod, and things directly connected to the iPod. Apple will stay on message. Given that the invite is in the shape of a guitar, the message is <strong>music</strong>.</p>
<p><strong>Update:</strong> Well, I was wrong about the <a href="http://www.apple.com/appletv/">Apple TV</a>, but I was right about cloud sync and the iPad nano.</p>]]></content:encoded>
    </item>
    <item>
      <title>A one day project</title>
      <link>https://tewha.net/2010/02/a-one-day-project/</link>
      <pubDate>Sat, 06 Feb 2010 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2010/02/a-one-day-project/</guid>
      <description>&lt;p&gt;I started work today on an iPhone project with a friend. I figured it would take only a day to get to a reasonable 1.0. I’ve only put in about a half day on it so far, but at this point I’m pretty sure it’s actually a two day project.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I started work today on an iPhone project with a friend. I figured it would take only a day to get to a reasonable 1.0. I’ve only put in about a half day on it so far, but at this point I’m pretty sure it’s actually a two day project.</p>
<p>Looked at one way, that’s a 200% estimation overflow. But more realistically, it means it was pretty small and I tackled it in the wrong way. I had to refactor some code early that I left alone for too long. I should’ve written in the right way to begin with, and I should have realized it was wrong sooner, and I should have stopped trying to make it work.</p>
<p>More pragmatically, maybe I should have known better. But, of course, I didn’t. And that’s okay! I know better now.</p>
<p>What’s my point in posting this?</p>
<p>Mostly, it’s this: <strong>iPhone development isn’t nearly as hard as I’ve made it out to be</strong>. Useful applications can actually be quite small and still be useful. Simple things are simple. When they’re not simple, it’s time to fix something.</p>
<p>I’ll post a link here when I finish the project. It’ll be a bit before I can devote another day to it. But I’m excited by its usefulness, its simplicity, and the idea of having an app in the App Store of my own.</p>]]></content:encoded>
    </item>
    <item>
      <title>Learning a new programming language</title>
      <link>https://tewha.net/2009/10/learning-a-new-programming-language/</link>
      <pubDate>Sat, 24 Oct 2009 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2009/10/learning-a-new-programming-language/</guid>
      <description>&lt;p&gt;It took me a while to learn Objective-C.&lt;/p&gt;
&lt;p&gt;I started at the most basic level, wondering at the language. What are these brackets? What’s with the @ signs? What’s the difference between a - and a +? These aren’t hard things to learn, but understanding the reasoning behind them helps. And then there’s a point where it suddenly makes sense.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>It took me a while to learn Objective-C.</p>
<p>I started at the most basic level, wondering at the language. What are these brackets? What’s with the @ signs? What’s the difference between a - and a +? These aren’t hard things to learn, but understanding the reasoning behind them helps. And then there’s a point where it suddenly makes sense.</p>
<p>But the framework was confusing. How do I do this? Though I was less confused, this one isn’t solved directly. I became competent. And I started to ask the best question: “Why?”</p>
<p>The patterns were still confusing. Why does this work this way? What’s the purpose of this? Why is this done, but not this other thing?</p>
<p>And then there was a point where the patterns became obvious. More, the pattern in the patterns became obvious to me. And now, I look to find more examples of patterns, and patterns of patterns, to better build my knowledge.</p>
<p>It took me a while to get here, and it’s the same for every language. I’m feeling pretty confident about Objective-C now.</p>
<p>Back on the first day, I was confused and lost.</p>]]></content:encoded>
    </item>
    <item>
      <title>The secret to enjoying Xcode</title>
      <link>https://tewha.net/2009/10/the-secret-to-enjoying-xcode/</link>
      <pubDate>Fri, 23 Oct 2009 14:00:00 +0000</pubDate>
      <guid>https://tewha.net/2009/10/the-secret-to-enjoying-xcode/</guid>
      <description>&lt;p&gt;One of the things that made me like Xcode more and become more efficient with it is realizing that while all coders are insane, me and Xcode’s designers are &lt;em&gt;insane in different ways&lt;/em&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>One of the things that made me like Xcode more and become more efficient with it is realizing that while all coders are insane, me and Xcode’s designers are <em>insane in different ways</em>.</p>
<p>By that, I mean that aside from the standard keyboard shortcuts (Save, Copy… that sort of thing), none of the keyboard shortcuts made sense to me.</p>
<p>So I duplicated one of the keyboard shortcut profiles and deleted most of the keyboard bindings. I was brutal with it — if the combination didn’t make sense to me OR it was something I’d rarely use it was removed. Then I added keyboard shortcuts that I needed. By using about an hour to customize these settings, I ended up having keyboard shortcuts that I fully understood and rolled off my fingertips.</p>
<p>At this point — and this is where it became a useful exercise — I added my <code>~/Library/Application Support/Xcode</code> to version control so I could easily sync it between computers. So when I find something that isn’t quite working out for me, I make a change and propagate it to my other system.</p>
<p>Am I going to share what I ended up with? No, because that’s not the point of this. Rather, I want to point out a simple fact of Xcode: <strong>Xcode will adapt to how you want to use it, and if you feel like you’re suffering at all with it you should spend the time it to takes to make it enjoyable to use.</strong></p>
<p>And when someone tells me I can do something with a particular keyboard shortcut, I switch back to the defaults and see what it’s bound to.</p>]]></content:encoded>
    </item>
    <item>
      <title>iTunes zoom behavior</title>
      <link>https://tewha.net/2009/09/itunes-zoom-behavior/</link>
      <pubDate>Thu, 24 Sep 2009 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2009/09/itunes-zoom-behavior/</guid>
      <description>&lt;p&gt;iTunes prior to 9.0 used a click on the zoom widget to convert to the mini player, leaving people like me who actually like to zoom a window option-clicking it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>iTunes prior to 9.0 used a click on the zoom widget to convert to the mini player, leaving people like me who actually like to zoom a window option-clicking it.</p>
<p>iTunes 9.0 finally fixed this. A click on the zoom widget actually zoomed the window!</p>
<p>iTunes 9.0.1 changed it back to the old behavior. Many people were happy, I imagine. But people who wanted to zoom iTunes windows (or, I imagine, valued standard behavior) were left sad.</p>
<p>It turns out you can get the click-to-zoom behavior back:</p>
<pre><code>defaults write com.apple.iTunes zoom-to-window -bool true
</code></pre>
<p>Tip of the hat to <a href="http://twitter.com/zadr">zadr</a> on Twitter for <a href="http://twitter.com/zadr/status/4300874028">this tweet</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>On skins and plugins</title>
      <link>https://tewha.net/2009/08/on-skins-and-plugins/</link>
      <pubDate>Sat, 15 Aug 2009 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2009/08/on-skins-and-plugins/</guid>
      <description>&lt;p&gt;I started this post over six months ago, but never quite got around to finishing it. It might never be finished. But this is a thorn to me, so I’m just going to post it as is.&lt;/p&gt;
&lt;p&gt;Should your new application support skins?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I started this post over six months ago, but never quite got around to finishing it. It might never be finished. But this is a thorn to me, so I’m just going to post it as is.</p>
<p>Should your new application support skins?</p>
<p>Probably not. Skins are often a programmer’s way of saying “Oh, I don’t do UI. We’ll let someone else get it right.” Only nobody ever does, at least not in your product. Your UI just isn’t as compelling <a href="http://www.codinghorror.com/blog/archives/000789.html">as the one it’s replacing</a>.</p>
<p>The corollary to this is that if lots of people are demanding skins, it means your UI sucks. Once you add skins, you’ll never be rid of those skins, and you won’t have fixed your application either.</p>
<p><strong>You’d probably do better to fix your application’s appearance and behavior.</strong></p>
<p>Now, should you do a custom appearance?</p>
<p>If you’re planning a completely custom appearance for your applications, odds are it will suck. Unless you have artists that are beyond simply competent, but brilliant, you’ll probably fail.</p>
<p>First, you need a UI that looks and feels good. Secondly, it probably needs to fit in with the native platform. If you’re planning a full screen game, it’s fine to not fit in. But if you’re building a Windows-based BIOS updater, that custom UI that you think looks so amazing? The truth is, it <a href="http://support.asus.com/technicaldocuments/technicaldocuments_content.aspx?no=714">looks like complete shit</a>.</p>
<p><strong>You’re better off fitting custom UI into the OS rather than changing your whole application to fit them.</strong></p>
<p>Now, finally: What about plugins?</p>
<p>This one is a little less clear. There’s great reasons to do plugins. Integration with another system (whether technical such as a web site or social such as particular requirements for reporting) is a good one.</p>
<p>But you know what isn’t a great reason? Making your product a <strong>platform</strong>. Do you want to be a product people use, or a platform people struggle with?</p>
<p>Firefox’s plugins make me flinch. They’re usually poor quality, craptacular tools that lunge for a particular nugget of a good idea and fall flat on their faces a few yards away from it. There are a few that are interesting, but they’d <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">benefit from being rolled in</a>, or being a <a href="https://addons.mozilla.org/en-US/firefox/addon/5817">separate stand-along product</a> on their own.</p>
<p>Pick your features carefully. 37signals didn’t become popular by picking an extensive list of features or allowing people to write their own features. Instead, they built something they wanted to use. And they’re not alone. There are a few things I’d love to see (<a href="http://daringfireball.net/projects/markdown/">Markdown</a> instead of <a href="http://textile.thresholdstate.com/">Textile</a>, for instance), but even if a hypothetical plugin system could add these things, they’d be overwhelmed by the layer of suck.</p>
<p><strong>Before you build a plugin architecture, put the effort into your application.</strong></p>]]></content:encoded>
    </item>
    <item>
      <title>Xcode and iPhone OS 3.0.1</title>
      <link>https://tewha.net/2009/07/xcode-and-iphone-os-3-0-1/</link>
      <pubDate>Fri, 31 Jul 2009 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2009/07/xcode-and-iphone-os-3-0-1/</guid>
      <description>&lt;p&gt;To get Xcode 3.1.3 working with iPhone OS 3.0.1, you’ll need to teach Xcode how to target iPhone OS 3.0.1.&lt;/p&gt;
&lt;p&gt;Xcode will automatically recognize iPhone OS 3.0.1 and look for a new SDK at a set path. The problem is that SDK doesn’t exist. The good part is that the iPhone OS 3.0 SDK works perfectly for developing 3.0.1. The only apparent change is the SMS fix.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>To get Xcode 3.1.3 working with iPhone OS 3.0.1, you’ll need to teach Xcode how to target iPhone OS 3.0.1.</p>
<p>Xcode will automatically recognize iPhone OS 3.0.1 and look for a new SDK at a set path. The problem is that SDK doesn’t exist. The good part is that the iPhone OS 3.0 SDK works perfectly for developing 3.0.1. The only apparent change is the SMS fix.</p>
<p>Assuming you’ve installed to /Developer, the iPhone OS 3.0 SDK is here:</p>
<pre><code>/Developer/Platforms/iPhoneOS.platform/DeviceSupport/3.0 (7A341)
</code></pre>
<p>When using Xcode with iPhone OS 3.0.1, Xcode looks for the iPhone OS 3.0.1 SDK here:</p>
<pre><code>/Developer/Platforms/iPhoneOS.platform/DeviceSupport/3.0.1&lt;/code&gt;
</code></pre>
<p>The trick, then, is to build a symbolic link that connects what Xcode is looking for with what it needs to find.</p>
<p>So what do you do? Assuming you’ve installed Xcode in the standard location, this is a Terminal command to fix the problem:</p>
<pre><code>ln -s /Developer/Platforms/iPhoneOS.platform/DeviceSupport
/3.0 (7A341) /Developer/Platforms/iPhoneOS.platform/
DeviceSupport/3.0.1
</code></pre>
<p>This will not add a SDK to Xcode’s list, it will just teach Xcode to map your device to the 3.0 SDK.</p>
<p>A few other tips:</p>
<ul>
<li>If you still can’t debug restarting your iPhone may help. Most of the iPhones I’ve tried to debug on, I’ve had to restart first.</li>
<li>If you get an error regarding code signing, try downloading your provisioning profile again and re-installing it. Also, select it again in your build settings.</li>
</ul>
<p>Based on information from <a href="http://developer.apple.com/iphone/download.action?path=/iphone/iphone_sdk_3.0__final/iphone_os_3.0.1_advisory.pdf">iPhone OS 3.0.1 Advisory</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Coding tips for new iPhone developers from a new iPhone developer</title>
      <link>https://tewha.net/2009/02/coding-tips-for-new-iphone-developers-from-a-new-iphone-developer/</link>
      <pubDate>Mon, 02 Feb 2009 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2009/02/coding-tips-for-new-iphone-developers-from-a-new-iphone-developer/</guid>
      <description>&lt;p&gt;If any of these seem wrong, please comment!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Objective-C syntax is strange. It’s really not that hard, though, especially once you realize that part of the reason for the design was to make Objective-C a strict superset of C. That means that the C code you throw at it will compile and means the same thing under C as Objective-C.&lt;/li&gt;
&lt;/ul&gt;</description>
      <content:encoded><![CDATA[<p>If any of these seem wrong, please comment!</p>
<ul>
<li>The Objective-C syntax is strange. It’s really not that hard, though, especially once you realize that part of the reason for the design was to make Objective-C a strict superset of C. That means that the C code you throw at it will compile and means the same thing under C as Objective-C.</li>
</ul>
<ul>
<li>
<p>Use <code>NULL</code> for pointers (<code>void*</code>) and <code>nil</code> for instances (<code>NSObject*</code>). They’re defined the same, this is just convention.</p>
<ul>
<li>
<p>Use properties and stay sane. You can leave the dot syntax alone if you like (though I like it), but it’s worth using properties anyway because it forces you to document the assignment mechanism you’re using.</p>
</li>
<li>
<p>Method names that return an object where the name does not contain <code>init</code> must not require the object be released.</p>
</li>
<li>
<p>If you’re writing the object, this means you’re probably calling <code>retain</code> and <code>autorelease</code>.</p>
</li>
<li>
<p>If you’re using the object, this means it is probably already calling <code>autorelease</code>. If you release the instance yourself, you’ll crash later.</p>
</li>
<li>
<p>Use <code>alloc</code>, <code>init</code> on the same line.</p>
</li>
<li>
<p>If you’re going to <code>autorelease</code> an object, do it at immediately on creation rather than later: <code>[[[Object alloc] init] autorelease]</code>.</p>
</li>
<li>
<p>Sure, you can avoid using <code>autorelease</code>. Sure, it would perform “better”. But can you quantify “better”? Is it significant to you? If it isn’t, stick with using <code>autorelease</code>. When you follow the rules, you idiotproof yourself. See the probably in the previous group of points? Stick with the rules and it’s basically an “always.”</p>
</li>
<li>
<p>Remember that debugging is harder than writing code. While you can write something like <code>textView.text = [NSString stringWithFormat:@&quot;%@: %d&quot;, [b field:@&quot;test&quot;], [a precision]];</code> you are going to have to debug it later. In most cases, you’ll benefit from assigning results to temporary variables before passing them through to Cocoa.</p>
</li>
</ul>
</li>
</ul>
<p>I’m going to write about the major device vs. simulator differences I’ve noticed another time, but there’s one worth mentioning now: <code>CGSize size = [string sizeWithFont:font]</code> with a nil string will return a zero point on the desktop, but will return a random value (stack, maybe?) on the device itself. Check for nil first, as in <code>CGSize size = string ? [string sizeWithFont:font] : CGSizeZero</code>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Macworld Keynote</title>
      <link>https://tewha.net/2009/01/macworld-keynote/</link>
      <pubDate>Sun, 11 Jan 2009 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2009/01/macworld-keynote/</guid>
      <description>&lt;p&gt;A few thoughts, based on watching the keynote via QuickTime:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Phil Schiller was great. He seemed to be a little nervous in his delivery, but he was interesting in a casual, friendly way. If he has a chance to do some of Apple’s special events in the future, he’ll be a little less awkward.&lt;/li&gt;
&lt;/ul&gt;</description>
      <content:encoded><![CDATA[<p>A few thoughts, based on watching the keynote via QuickTime:</p>
<ul>
<li>Phil Schiller was great. He seemed to be a little nervous in his delivery, but he was interesting in a casual, friendly way. If he has a chance to do some of Apple’s special events in the future, he’ll be a little less awkward.</li>
</ul>
<ul>
<li>
<p>From any other company, this would have been a slam dunk, and people who are unhappy are clearly expecting too much.</p>
<ul>
<li>
<p>The iLife 09 upgrades make it a must-have purchase for me. I’m looking forward to working through the Garage Band tutorials, and iPhoto face and location metadata is an omission I’ve been struggling to find workarounds to. And as an owner of a Flip Ultra, I’m really looking forward to having image stabilization.</p>
</li>
<li>
<p>The 17” MacBook built-in battery seems like a great trade-off to me. I don’t have two batteries anymore, I just replace the one I have when it won’t hold enough charge anymore. It sounds like that will still be possible.</p>
</li>
<li>
<p>I’m really happy to see DRM-free music on the iTunes Store. I’m less impressed with the all-or-nothing upgrade, but will probably upgrade sooner or later.</p>
</li>
</ul>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Loving Xcode &#43; iPhone SDK</title>
      <link>https://tewha.net/2008/12/loving-xcode-iphone-sdk/</link>
      <pubDate>Mon, 15 Dec 2008 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/12/loving-xcode-iphone-sdk/</guid>
      <description>&lt;p&gt;I’ve been full time on an iPhone project (more of a prototype, really) for one day, and I absolutely love it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I’ve been full time on an iPhone project (more of a prototype, really) for one day, and I absolutely love it.</p>
<ul>
<li>
<p>It’s simple and intuitive. Drop controls, set up outlets and actions.</p>
<ul>
<li>
<p>You don’t have to fight the framework. It does what it does with a minimum of fuss.</p>
</li>
<li>
<p>A good UI is a focused UI, rather than one full of features. I love this style of thinking.</p>
</li>
</ul>
</li>
</ul>
<p>I’m less thrilled with Xcode’s documentation viewer. It feels like a really poor web browser that takes more of the screen for junk, runs in the same workspace so you can’t command-tab in and out of it. Just splitting it into a separate process would immediately improve it.</p>
<p>In about a day, I created four screens and linked them all together. That doesn’t sound horribly impressive, but it felt easy. Granted, I’ve previously spent a few hours figuring out <code>UINavigationController</code>, but things were actually simpler than I had understood. Finding things took a while, but they were generally hidden in plain sight. The few times I violated something in the runtime, the error message was simple, direct and accurate.</p>
<p>I do wish <a href="http://www.sqlite.org">SQLite</a> was a more recent version. I would love to use <a href="http://www.sqlite.org/c3ref/open.html">sqlite3_open_v2</a> in some of this code, especially the <code>SQLITE_OPEN_READONLY</code> flag.</p>]]></content:encoded>
    </item>
    <item>
      <title>Mac OS X interface flaws</title>
      <link>https://tewha.net/2008/11/mac-os-x-interface-flaws/</link>
      <pubDate>Fri, 28 Nov 2008 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/11/mac-os-x-interface-flaws/</guid>
      <description>&lt;p&gt;Here are a few things I’ve noticed that just don’t make sense in Mac OS X v10.5.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Desktop &amp;amp; Screen Saver rolled into a single preference pane. Why? Are we that convinced that one day we’re going to have a screen saver running in the background as our desktop, and the only way to configure it is to have it in the same preference panel?&lt;/li&gt;
&lt;/ul&gt;</description>
      <content:encoded><![CDATA[<p>Here are a few things I’ve noticed that just don’t make sense in Mac OS X v10.5.</p>
<ul>
<li>Desktop &amp; Screen Saver rolled into a single preference pane. Why? Are we that convinced that one day we’re going to have a screen saver running in the background as our desktop, and the only way to configure it is to have it in the same preference panel?</li>
</ul>
<ul>
<li>
<p>Keyboard &amp; Mouse are a single preference panel (but Trackpad is separate). Again, why? The only conceivable answer is that Apple thought it important that the battery levels for both the keyboard and mouse are in a single preference pane, which also has an option to add a new device. But the “add device” functionality is already duplicated in Bluetooth.</p>
<ul>
<li>
<p>Exposé &amp; Spaces are a single preference panel. Are they related? Well, a little, but not that much. And how does Dashboard fit in here, which is also thrown in for fun?</p>
</li>
<li>
<p>Translucent Menu Bar is in Desktop, rather than Appearance.</p>
</li>
<li>
<p>Scroll bar behavior is in Appearance.</p>
</li>
<li>
<p>The number of recent items to show in menus is in Appearance.</p>
</li>
<li>
<p>The option to automatically adjust keyboard back lighting is under Displays. (But typing “Dim” into the preference pane search only hilights the Energy Saver panel.)</p>
</li>
</ul>
</li>
</ul>
<p>Oh, sure, it’s better than Windows. Of that there’s no doubt. And sure, we got here via a series of small, well-intentioned steps. But let’s not get too smug about Mac OS X: It still needs a lot of tuning to be intuitive.</p>]]></content:encoded>
    </item>
    <item>
      <title>Microsoft doesn’t get it</title>
      <link>https://tewha.net/2008/09/microsoft-doesnt-get-it/</link>
      <pubDate>Sat, 20 Sep 2008 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/09/microsoft-doesnt-get-it/</guid>
      <description>&lt;p&gt;The new Microsoft commercial starts with a John Hodgman dressalike (You can’t really call him a lookalike, but at the distance the camera is at it doesn’t matter) saying “I’m a PC and I’ve been stereotyped.” It then goes to various people asserting they’re a PC. It’s interesting at first, but after a few seconds you realize: This is all Microsoft’s got for this commercial. After a minute of droning, the commercial blissfully comes to an end.&lt;/p&gt;
&lt;p&gt;It makes slightly more sense than the Gates &amp;amp; Seinfeld commercials, but replaces the quirkiness of those ads with banality.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>The new Microsoft commercial starts with a John Hodgman dressalike (You can’t really call him a lookalike, but at the distance the camera is at it doesn’t matter) saying “I’m a PC and I’ve been stereotyped.” It then goes to various people asserting they’re a PC. It’s interesting at first, but after a few seconds you realize: This is all Microsoft’s got for this commercial. After a minute of droning, the commercial blissfully comes to an end.</p>
<p>It makes slightly more sense than the Gates &amp; Seinfeld commercials, but replaces the quirkiness of those ads with banality.</p>
<p>The commercial shows Microsoft doesn’t get the concept behind Apple’s “Get a Mac” ads. Hodgman is not the personification of Windows, and Justin Long is no the personification of Mac. Hodgman is a PC, like he says. Long is a Mac, like he says.</p>
<p>What does that mean? Well, it means that the difference between Long and Hodgman is the ability to run Mac OS X. Long can, and Hodgman can’t. PC’s secret motivation — an undercurrent running through all the commercials that Apple will never vocalize — is that he’s jealous. He knows he can do all the things a PC can do. He wants to do all the things a Mac can do, too. His motives, then, are minimizing the value of Mac OS X: It isn’t <strong>really</strong> that simple. It isn’t <strong>really</strong> that easy. You don’t really <strong>need</strong> that, you can do it without a Mac.</p>
<p>But PC doesn’t really believe it. He knows he can do everything Mac can do. He just also knows he can’t do it as easily. So the secret behind the motivation he won’t state is this: He wants to run Mac OS X, too. And Apple will never vocalize this, because it inspires the question to the masses: Why can’t PC run Mac OS X? ((Sure, there’s lots of good reasons. I’m not denying that. I’m also not denying they are probably all solvable. I’m just pointing out that Apple doesn’t really want people choosing between a Mac and a PC to ask the question, but just to take it for granted.))</p>
<p>So Microsoft runs this ad, showing all the things PC can do. Great. Each one of them is something Mac can do, too.</p>
<p>Microsoft needs to focus on promoting their product, not someone else’s product. And Microsoft does not sell generic PCs. But what does Microsoft sell, really? What are they going to brag about on Windows? Why do they need to?</p>
<p>Every time Microsoft puts out a commercial, they blink. And they don’t have to at this point.</p>]]></content:encoded>
    </item>
    <item>
      <title>WarpedVisions on Objective-C, square 1</title>
      <link>https://tewha.net/2008/08/warpedvisions-on-objective-c-square-1/</link>
      <pubDate>Sun, 24 Aug 2008 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/08/warpedvisions-on-objective-c-square-1/</guid>
      <description>&lt;p&gt;Bruce over on WarpedVisions writes on &lt;a href=&#34;http://warpedvisions.org/2008/08/24/objective-c-square-1&#34;&gt;entering the world of Objective-C and Cocoa development&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Bruce over on WarpedVisions writes on <a href="http://warpedvisions.org/2008/08/24/objective-c-square-1">entering the world of Objective-C and Cocoa development</a>.</p>
<p>I’m barely past square one, but I found this an interesting title. Of course, what Bruce means is the whole Mac OS X development experience, but it’s interesting that he worded it in the title as learning Objective-C. It’s a simple, concise yet technically inaccurate way to label the knowledge. ((And I’m not intentionally picking on Bruce here. I have said it this way, and probably will again, and he <em>does</em> get it right in the text, as he noted below.))</p>
<p>Objective-C just might be the easiest part of Mac OS X development. The hard part is simply knowing what objects are available in Cocoa, where they are, and how to string them together. Basically, the typical framework problem. Don’t get me wrong, I’m still at the very bottom of the learning curve here!</p>
<p>Objective-C itself is very nice; it’s a truly minimal extension to C. I’m amazed at how it’s still a very complete object-oriented language yet so simple and small, with everything done the simple way.</p>
<p>When I first started with Cocoa, I was thinking of compiling notes together so I could write a short book/essay on “Learning Cocoa for C++ developers,” but as I’ve gone I’ve realized the first chapter should be “Forget everything you know about C++. You think need ___ to do <strong><em>? You do in C++, but in Objective-C just use the Cocoa class</em></strong>.”</p>]]></content:encoded>
    </item>
    <item>
      <title>The sad case of Palm</title>
      <link>https://tewha.net/2008/08/the-sad-case-of-palm/</link>
      <pubDate>Tue, 19 Aug 2008 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/08/the-sad-case-of-palm/</guid>
      <description>&lt;p&gt;I first started developing an application for Palm in 2000 with the Palm IIIc. I was amazed at how well-thought out the API was. A few things were missing, such as POSIX-compatible routines. ((Expecting full POSIX support on a Palm back then was maybe a little unrealistic, but expecting the available routines to match POSIX definitions is quite a bit more reasonable.)) The API looked a lot like Carbon, which was a perfectly reasonable way to develop applications. CodeWarrior was a decent-enough tool, and growing in capabilities. New hardware, while not announced or even previewed yet, was on the horizon that could take away most of the nastiest problems with Palm OS, which were rooted in the 680x0 architecture.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I first started developing an application for Palm in 2000 with the Palm IIIc. I was amazed at how well-thought out the API was. A few things were missing, such as POSIX-compatible routines. ((Expecting full POSIX support on a Palm back then was maybe a little unrealistic, but expecting the available routines to match POSIX definitions is quite a bit more reasonable.)) The API looked a lot like Carbon, which was a perfectly reasonable way to develop applications. CodeWarrior was a decent-enough tool, and growing in capabilities. New hardware, while not announced or even previewed yet, was on the horizon that could take away most of the nastiest problems with Palm OS, which were rooted in the 680x0 architecture.</p>
<p>I estimated at the time they were at least four years ahead of the competition in terms of an operating system.</p>
<p>But since then?</p>
<p>Buying and selling themselves to… themselves.</p>
<p>Absolutely nothing on the OS front.</p>
<p>Since then? Windows CE and successors have caught up in many areas, exceeded Palm in others. Blackberry, and iPhone exist, both of which make Palm look pathetic.</p>
<p>Loss of professional-level development tools.</p>
<p>Hardware quality control problems.</p>
<p>It’s hard to believe that Palm has thrown away this much of a lead. But they have.</p>]]></content:encoded>
    </item>
    <item>
      <title>LaCie Quadra d2</title>
      <link>https://tewha.net/2008/08/lacie-quadra-d2/</link>
      <pubDate>Sat, 02 Aug 2008 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/08/lacie-quadra-d2/</guid>
      <description>&lt;p&gt;It’s way too early to tell if LaCie is still the “all that and a bag of chips” hard drive company, but I can tell you this right away: The case is the best external case I’ve ever personally bought, and probably better than the stackable system Discovery bought from LaCie over a decade ago. It’s extremely solid, aluminum and rippled like a heatsink.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>It’s way too early to tell if LaCie is still the “all that and a bag of chips” hard drive company, but I can tell you this right away: The case is the best external case I’ve ever personally bought, and probably better than the stackable system Discovery bought from LaCie over a decade ago. It’s extremely solid, aluminum and rippled like a heatsink.</p>
<p>I think the case itself is fanless, but of course it does have vents and the hard drive inside does whir. So it isn’t silent, but is very quiet.</p>
<p>A matching mini rack is available, though I didn’t purchase one yet. I plan to buy a 750GB or 1TB drive in another couple months to back up to, and will probably pick up the rack then as well. In the meantime, I’m back to doing manual backups of my photos and music.</p>
<p>Running from this hard drive for even an hour has convinced me that my Mac mini’s hard drive is indeed failing. I’d be a lot more annoyed at that if I didn’t have the Quadra to run from while waiting for the replacement hard drive.</p>]]></content:encoded>
    </item>
    <item>
      <title>Hot hardware</title>
      <link>https://tewha.net/2008/05/hot-hardware/</link>
      <pubDate>Tue, 27 May 2008 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/05/hot-hardware/</guid>
      <description>&lt;p&gt;I’ve been using this iMac for a few weeks, and I’ve noticed an odd melty-plastic smell from time to time. I didn’t associate it with the iMac, though; the top of the iMac was hot, but not unbearably so.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I’ve been using this iMac for a few weeks, and I’ve noticed an odd melty-plastic smell from time to time. I didn’t associate it with the iMac, though; the top of the iMac was hot, but not unbearably so.</p>
<p>After the weekend, though, the smell was more intense. <a href="http://warpedvisions.org">Bruce</a> found a particular spot on the back panel of it that was uncomfortably hot. Time to investigate.</p>
<p>I downloaded <a href="http://www.bresink.com/osx/TemperatureMonitor.html">Temperature Monitor</a> and found the power supply was at 81° Celsius (about 178° Fahrenheit). That’s far too hot! I found <a href="http://homepage.mac.com/holtmann/eidac">smcFanControl</a> and turned up the fan speeds, and my iMac’s power supply is runs between 55-58° Celsius (131-136° Fahrenheit). That’s much healthier, and the plasticy smell has almost (but not completely) disappeared. The downside is that the iMac is no longer silent, though I’m pretty sure I can turn the fans down slightly over the next few weeks.</p>
<p>I appreciate that Apple was trying to make my workspace more enjoyable by keeping the volume down, but it turns out the smell of burning plastic is more distracting than the fan noise. I can only imagine being without a computer while the power supply and back panel were replaced would have been even more distracting.</p>]]></content:encoded>
    </item>
    <item>
      <title>Props to Simply Computing</title>
      <link>https://tewha.net/2008/04/props-to-simply-computing/</link>
      <pubDate>Tue, 29 Apr 2008 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/04/props-to-simply-computing/</guid>
      <description>&lt;p&gt;I picked up a nice, shiny 24” iMac on Friday from &lt;a href=&#34;http://www.simply.ca&#34;&gt;Simply Computing&lt;/a&gt; in Langley for my employer to replace my elderly Core Solo mini. Monday, Apple refreshed the model. I realized I didn’t actually mind &lt;strong&gt;at all&lt;/strong&gt;, but it seemed it might be worth a quick email:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I picked up a nice, shiny 24” iMac on Friday from <a href="http://www.simply.ca">Simply Computing</a> in Langley for my employer to replace my elderly Core Solo mini. Monday, Apple refreshed the model. I realized I didn’t actually mind <strong>at all</strong>, but it seemed it might be worth a quick email:</p>
<blockquote>
<p>I was just wondering if you guys have some sort of “Apple dropped my model the next business day!” policy. I’m not going to lie here – I’m actually satisfied with the old model, I just thought since the timing was so perfect it was worth a two sentence email.</p>
</blockquote>
<p>The result? A $200 in-store credit. Which, bluntly, was more than I ever expected. I didn’t have to lie for it, which is good because I wouldn’t have done so. All I had to do is ask.</p>
<p>Thanks, Simply. That was a classy move. I really respect these guys. They’re honest, practical, and not out to screw anyone.</p>]]></content:encoded>
    </item>
    <item>
      <title>One App At a Time… Always?</title>
      <link>https://tewha.net/2008/03/one-app-at-a-time-always/</link>
      <pubDate>Fri, 14 Mar 2008 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/03/one-app-at-a-time-always/</guid>
      <description>&lt;p&gt;Gruber at Daring Fireball &lt;a href=&#34;http://daringfireball.net/2008/03/one_app_at_a_time&#34;&gt;writes about the restriction&lt;/a&gt; of one application at a time on the iPhone. Read it before you go on.&lt;/p&gt;
&lt;p&gt;Writing a background task for Touch OS X would be very, very hard. Well, actually, not so much hard as taking a lot of skill, time and effort. I can really understand why Apple wouldn’t want just anyone doing it. But before I get too stressed over it, it’s worth asking a few questions:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Gruber at Daring Fireball <a href="http://daringfireball.net/2008/03/one_app_at_a_time">writes about the restriction</a> of one application at a time on the iPhone. Read it before you go on.</p>
<p>Writing a background task for Touch OS X would be very, very hard. Well, actually, not so much hard as taking a lot of skill, time and effort. I can really understand why Apple wouldn’t want just anyone doing it. But before I get too stressed over it, it’s worth asking a few questions:</p>
<p>First, what kind of program does this actually affect? Not many, probably. In fact, basically, polling network software or network software that receives pushes is the most common scenario. ((Time-based software is also a possibility, but let’s discard that for the moment.)) An instant messenger program is an obvious example; it needs to keep the connection alive and plays some sort of beep when a message comes in.</p>
<p>So we’ve established a program this affects. Now it’s worth asking a second question: Is it possible this rule is up for negotiation? At the right price, would it go away? And if so, what might the right price be?</p>
<ul>
<li>An application that background operation is critical to.</li>
<li>An application that Apple thinks is important enough to be worth the resources on the iPhone and the effort. Because make no mistake, it’s going to take effort from Apple.</li>
<li>Doing the work on campus with an Apple engineer’s help.</li>
<li>Payment for the engineer, possibly to be waived in some cases.</li>
</ul>
<p>In short, if I was to write a program that beeped on the hour, I probably wouldn’t get an exception. I wouldn’t even know who to ask. But AOL Instant Messenger? That might happen. AOL might not even have to ask. (Although I doubt they have anything running in the background at this point. For the purposes of a prototype/demo, a simple, customized back end would make more sense.)</p>
<p>As developers we need to worry more about <strong>we</strong> are going to do, than what someone like AOL is going to do.</p>]]></content:encoded>
    </item>
    <item>
      <title>.Mac thoughts</title>
      <link>https://tewha.net/2008/02/mac-thoughts/</link>
      <pubDate>Wed, 27 Feb 2008 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/02/mac-thoughts/</guid>
      <description>&lt;p&gt;So I’m about five days into my free .Mac trial, and I thought I’d write up some thoughts.&lt;/p&gt;
&lt;p&gt;I pay about $60 per year for 500 GB of storage and 5 TB of bandwidth from &lt;a href=&#34;http://www.dreamhost.com/r.cgi?67943&#34;&gt;DreamHost&lt;/a&gt;. .Mac costs $100 per year. For that much, it should be really, really special. On a strictly numerical level, DreamHost beats .Mac. Now, it’s true that DreamHost’s reputation for reliability has taken a beating the last year or so, but for $6 per month I can accept a few days per month of down time. And it’s nowhere &lt;em&gt;near&lt;/em&gt; that bad; it seems to be less than one evening every month or two.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>So I’m about five days into my free .Mac trial, and I thought I’d write up some thoughts.</p>
<p>I pay about $60 per year for 500 GB of storage and 5 TB of bandwidth from <a href="http://www.dreamhost.com/r.cgi?67943">DreamHost</a>. .Mac costs $100 per year. For that much, it should be really, really special. On a strictly numerical level, DreamHost beats .Mac. Now, it’s true that DreamHost’s reputation for reliability has taken a beating the last year or so, but for $6 per month I can accept a few days per month of down time. And it’s nowhere <em>near</em> that bad; it seems to be less than one evening every month or two.</p>
<p>So that leaves a comparison of features. Now, actually there’s very little overlap between the two. .Mac offers a bare minimum of traditional web hosting features, with low bandwidth and storage, and few of the more dynamic features such as SQL and PHP. DreamHost offers huge bandwidth, huge storage, and lots of dynamic features.</p>
<p>As a traditional webhost, DreamHost wins hands down. But .Mac offers a lot that DreamHost doesn’t.</p>
<p>Apple lists the features of .Mac as Web Gallery, Website Hosting, IMAP email, Back to My Mac, Sync, iDisk, Groups, Backup, and 10 GB storage. There’s also easy publishing with the iApps. The webmail interface shames DreamHost’s webmail, but I download all my email anyway. The most useful-looking features are syncing and Back to My Mac.</p>
<p>Back to My Mac doesn’t work at all for me. There’s no errors, no feedback at all – it just isn’t there where it’s supposed to be. I’ve done a bit of research on this, and I expect it’s because my NAT doesn’t support the features Back to My Mac needs. But this is really just a guess, since there’s no feedback at all.</p>
<p>At first glance, syncing seemed to work for me. But then I ran into an odd problem: The sync created duplicates of a bunch of smart mail boxes. No problem, though: Delete them, reset up to .Mac. It’ll propagate to the other computers, right? Well, it turns out that’s a bad assumption. It worked to a point, but then one of the other computers just adds them again. I’d basically need to delete them from both computers simultaneously in order to get rid of them. No problem, I’ll just use Back to My Mac.</p>
<p>Oh, wait. That’s not going to work.</p>
<p>Well, maybe I’ll check out .Mac in another few years. But for now, I can’t imagine spending $100 on it. I want something that takes the gremlins out of a multi-machine existence, rather than adding bigger, more annoying ones. I feel like I started with a mogwai and .Mac fed it after midnight. Maybe if I was a bigger webmail user or wasn’t comfortable setting up things like WordPress it would be more interesting, but I’m not that guy.</p>]]></content:encoded>
    </item>
    <item>
      <title>Apple claims fix to Time Machine security bug</title>
      <link>https://tewha.net/2008/02/apple-claims-fix-to-time-machine-security-bug/</link>
      <pubDate>Mon, 11 Feb 2008 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/02/apple-claims-fix-to-time-machine-security-bug/</guid>
      <description>&lt;p&gt;Apple claims to have fixed the issue where applications could run automatically &lt;a href=&#34;https://tewha.net/2007/11/mac-os-x-runs-deleted-applications/&#34;&gt;out of a Time Machine backup&lt;/a&gt;. Look for CVE-2008-0038 in Apple’s &lt;a href=&#34;http://docs.info.apple.com/article.html?artnum=307430&#34;&gt;About the security content of Mac OS X 10.5.2 and Security Update 2008-001&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Apple claims to have fixed the issue where applications could run automatically <a href="/2007/11/mac-os-x-runs-deleted-applications/">out of a Time Machine backup</a>. Look for CVE-2008-0038 in Apple’s <a href="http://docs.info.apple.com/article.html?artnum=307430">About the security content of Mac OS X 10.5.2 and Security Update 2008-001</a>.</p>
<p>Thanks to Apple for mentioning me. I certainly would have reported the bug regardless, but it’s a nice bonus.</p>
<p>The only thing I wish had happened differently was an earlier acknowledgement from Apple that they realized what I was describing and agreed it was a security problem. I didn’t find out Apple considered it a problem until January 22nd, when they asked how I’d like to be credited for discovery. Most of that time I wondered if I should file more details in an attempt to convince them it really was a problem. But, of course, that’s Apple’s nature.</p>]]></content:encoded>
    </item>
    <item>
      <title>Hierarchical menus suck</title>
      <link>https://tewha.net/2008/01/hierarchical-menus-suck/</link>
      <pubDate>Fri, 04 Jan 2008 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2008/01/hierarchical-menus-suck/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;http://daringfireball.net/2008/01/where_keyboard_shortcuts_win&#34;&gt;Where Keyboard Shortcuts Win&lt;/a&gt;, Gruber talks about Tog’s findings on mouse vs. keyboard. In a footnote, he adds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Especially with most Cocoa apps, where the Find commands are in a sub-menu, and thus take even longer to target using the mouse.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To me, this is a real problem on Mac OS. It is not one that Apple has not only completely failed to address, but has actually made worse in Mac OS X. For technical users, items in hierarchical menus are slightly more difficult to activate. But for non-technical users, items in hierarchical menus are &lt;strong&gt;not&lt;/strong&gt; just a little more difficult to activate, but &lt;strong&gt;awesomely&lt;/strong&gt; so. And in Mac OS X, Apple has introduced &lt;em&gt;more&lt;/em&gt; of them!&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In <a href="http://daringfireball.net/2008/01/where_keyboard_shortcuts_win">Where Keyboard Shortcuts Win</a>, Gruber talks about Tog’s findings on mouse vs. keyboard. In a footnote, he adds:</p>
<blockquote>
<p>Especially with most Cocoa apps, where the Find commands are in a sub-menu, and thus take even longer to target using the mouse.</p>
</blockquote>
<p>To me, this is a real problem on Mac OS. It is not one that Apple has not only completely failed to address, but has actually made worse in Mac OS X. For technical users, items in hierarchical menus are slightly more difficult to activate. But for non-technical users, items in hierarchical menus are <strong>not</strong> just a little more difficult to activate, but <strong>awesomely</strong> so. And in Mac OS X, Apple has introduced <em>more</em> of them!</p>
<p>Hierarchical menus have become a little better now that you don’t have to hold down the mouse button ((And, in fact, this suggests a simple fix Apple could do: Clicking an item with a hierarchical menu should lock that hierarchical menu open so the user can take as long as they want and use whatever motion they want to get into the hierarchical menu.)), but watching a neophyte or novice try to access them is a real eye-opener. I’d really suggest to any developer thinking of using one that they ask a non-technical person to select one. Using the mouse at all is the first major task. Using the mouse to select menu items is almost as difficult. And using the mouse to select menu items in hierarchal menus will often be more difficult than the previous two combined. It’s not only conceptually screwy, but physically difficult.</p>
<p>After doing so with a product used by teachers (including the almost-ready-to-retire), I removed every hierarchical menu from our application. There weren’t many anyway. But one of the most difficult things for me when moving from Mac OS Classic to Mac OS X was how obvious it was that Apple <em>hadn’t</em> tested this.</p>
<p>Now I’m not altogether opposed to hierarchical menus. I think they’re a perfectly valid solution for Services, Open With and maybe even Arrange By ((Arrange By is a valid place to use them only because novices and neophytes are probably looking to arrange by name most often, and that’s easily achieved by switching to list view.)). All of these options can be accessed some other way, except for Services which are rarely used by novices or neophytes. I also think they’re fine for contextual menus, since contextual menus only offer choices that are available elsewhere. (Or should. See <a href="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGMenus/chapter_16_section_5.html#//apple_ref/doc/uid/TP30000356-TPXREF113">Apple’s Human Interface Guidelines on Contextual Menus</a>.) But having Find commands in a hierarchical menu? That’s completely completely insane. Find is something users need to be able to access.</p>
<p>Apple even admits this problem in <a href="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGMenus/chapter_16_section_3.html#//apple_ref/doc/uid/TP30000356-TPXREF122">Apple Human Interface Guidelines</a>:</p>
<blockquote>
<p>Because submenus add complexity to the interface and are physically more difficult to use, you should use them only when you have more menus than fit in the menu bar</p>
</blockquote>
<p>So far, so good. But they go on:</p>
<blockquote>
<p>…or for closely related commands.</p>
</blockquote>
<p>This simply does not follow! Making something physically more difficult to use just because it’s closely related to something else is stupid. A good design puts commands in recognizable locations, and puts commands users need to access <strong>in locations that are easy to physically access</strong>. Closely related is <em>not</em> an excuse for a hierarchical menu. Closely related <em>and</em> infrequently used ((Or an option with an easier access method.)) is a good reason, though. But what genius decided that spell checking and find qualified? If find qualifies as infrequently used, it’s almost certainly because it’s such as a pain in the ass to select!</p>
<p>I do think this is less of a problem now that the menu search has been added to the Help menu. I find myself using this frequently in applications with many infrequently-used menu entries. ((Another symptom of lack of zen in application design. A few unused commands are normal but when a menu bar consists almost entirely of unused commands there’s a problem.))</p>]]></content:encoded>
    </item>
    <item>
      <title>HTML search fields</title>
      <link>https://tewha.net/2007/11/html-search-fields/</link>
      <pubDate>Sat, 24 Nov 2007 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/11/html-search-fields/</guid>
      <description>&lt;p&gt;A few days ago I re-added a search field to this site. I was pleasantly surprised at how easy it was; the CSS was a little fussy, but that’s more of a fun puzzle than a hard problem.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>A few days ago I re-added a search field to this site. I was pleasantly surprised at how easy it was; the CSS was a little fussy, but that’s more of a fun puzzle than a hard problem.</p>
<p>However, it took a long time to get the search field itself (which uses <a href="http://weblogs.mozillazine.org/hyatt/archives/2004_07.html#005890">input type=”search”</a>) working nicely on the iPod touch. Of course, it turned out to be my fault: My CSS had an extra <code>}</code> in it just above the entry that limited the field’s width. So the width is properly limited to something reasonable now. On the other hand, the search field doesn’t seem to get a different appearance from the text field or the search history. I can live with that.</p>
<p>It seems to degrade fairly nicely on other browsers. Of course, it doesn’t get the grey “click here to search”-type text, but I don’t really feel that’s worth adding. Hopefully, this will be adopted by the standard and end up in other browsers, too. In the meantime, I can live with this limitation, too. It certainly makes the code cleaner.</p>
<p>More on the input tag another time</p>]]></content:encoded>
    </item>
    <item>
      <title>Your app has a job, and it isn’t updating itself.</title>
      <link>https://tewha.net/2007/11/your-app-has-a-job-and-it-isnt-updating-itself/</link>
      <pubDate>Wed, 14 Nov 2007 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/11/your-app-has-a-job-and-it-isnt-updating-itself/</guid>
      <description>&lt;p&gt;WarpedVisions has an article on &lt;a href=&#34;http://warpedvisions.org/2007/11/14/boot-to-windows-do-not-pass-go&#34;&gt;automatic updates imposing on users&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve done some thinking on this subject.&lt;/p&gt;
&lt;p&gt;Should you wait on an update check before presenting the UI? Should you ask them if they want to update? If they do want to update, should they need to go through a web browser to download the update? Should it be a standard installer?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>WarpedVisions has an article on <a href="http://warpedvisions.org/2007/11/14/boot-to-windows-do-not-pass-go">automatic updates imposing on users</a>.</p>
<p>I’ve done some thinking on this subject.</p>
<p>Should you wait on an update check before presenting the UI? Should you ask them if they want to update? If they do want to update, should they need to go through a web browser to download the update? Should it be a standard installer?</p>
<p>One principle I like for automatic update is this:</p>
<p><strong>Assume the user launched your application because they want to do something.</strong></p>
<p>All of these questions have answers that developers assume they know, but when you start looking at it from a user perspective, things are very different.</p>
<h2 id="update_checks_shouldnt_be_blocking">Update checks shouldn’t be blocking.</h2>
<p>Should you wait on an update check before presenting the UI? Let’s imagine your host goes down, and the user is stuck waiting and waiting for your application to launch. Or maybe the host is just slow; that’s even worse. The <em>best</em> case is the user is disconnected from the Internet and failure is immediate.</p>
<p>This doesn’t mean you shouldn’t start a check, of course. Go ahead. Make it run in the background. If the check finishes before the UI is loaded, you can adjust the UI. Otherwise, you can remember for next launch.</p>
<h2 id="update_requests_shouldnt_be_blocking_either">Update requests shouldn’t be blocking, either.</h2>
<p>Decide if you’re going to apply the update automatically or not. The answer should usually be no.</p>
<p>If the update does need to be applied automatically, install it when it won’t impose (if you can judge when that will be, and if such a situation even exists).</p>
<p>If the user doesn’t need to update immediately, offer the update in a prominent place within your program, but don’t make them click to refuse it. Clicking “Not Now” is just going to become a habit. And don’t just tell them a new version is available and direct them to a web site. <strong>When they want to investigate, tell them why they’d want it!</strong> Replace nagging with good information.</p>
<h2 id="make_the_update_as_painfree_as_possible">Make the update as pain-free as possible.</h2>
<p>Download the update yourself. Whether automatically or on-demand, apply it yourself.</p>
<p>The decision whether to apply the update can be a painful one for users. It’s your job as a developer to provide the information users need to make that decision, and to do it in a way that encourages (rather than demands) the decision be made, and to eliminate any unnecessary pain associated with the update.</p>]]></content:encoded>
    </item>
    <item>
      <title>New in Leopard: Global Login Items?</title>
      <link>https://tewha.net/2007/11/new-in-leopard-global-login-items/</link>
      <pubDate>Wed, 07 Nov 2007 08:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/11/new-in-leopard-global-login-items/</guid>
      <description>&lt;p&gt;Not a lot of details yet, but apparently Mac OS X 10.5 supports Global Login Items. This would be a nice thing to have more information on, as I can imagine needing to remove these.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Not a lot of details yet, but apparently Mac OS X 10.5 supports Global Login Items. This would be a nice thing to have more information on, as I can imagine needing to remove these.</p>
<p>From Apple’s technote on <a href="http://developer.apple.com/technotes/tn2005/tn2083.html#SECGLOBALLOGINITEM">Daemons and Agents</a>:</p>
<blockquote>
<p>A <strong>global login item</strong> is a login item that is launched when any user logs in. Installing a global login item is roughly equivalent to installing that login item for all users on the system: every time a user logs in, loginwindow launches that user’s login items and all global login items.</p>
</blockquote>
<blockquote>
<p>In Mac OS X 10.5 and later you can install a global login item using the shared file lists interface to Launch Services.</p>
</blockquote>
<p>I’m getting the feeling from that description that there’s no UI for managing these. There’s also the possibility that some doc writer made the whole thing up. Anyone know more?</p>]]></content:encoded>
    </item>
    <item>
      <title>Mac OS X runs deleted applications</title>
      <link>https://tewha.net/2007/11/mac-os-x-runs-deleted-applications/</link>
      <pubDate>Thu, 01 Nov 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/11/mac-os-x-runs-deleted-applications/</guid>
      <description>&lt;p&gt;I filed this as radar #5574036, but it seems significant to share:&lt;/p&gt;
&lt;p&gt;Imagine that you trash an application because of a security flaw. Say, it handles the URL type foofoo, and is proven to be a security risk. But the developer won’t fix it (or hasn’t fixed it yet), so you’ve removed the application from your hard drive to keep yourself safe.&lt;/p&gt;
&lt;p&gt;It doesn’t work that way — you’re not safe. Time machine has made a copy in your time machine backup that Mac OS X will cheerfully launch without a warning.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I filed this as radar #5574036, but it seems significant to share:</p>
<p>Imagine that you trash an application because of a security flaw. Say, it handles the URL type foofoo, and is proven to be a security risk. But the developer won’t fix it (or hasn’t fixed it yet), so you’ve removed the application from your hard drive to keep yourself safe.</p>
<p>It doesn’t work that way — you’re not safe. Time machine has made a copy in your time machine backup that Mac OS X will cheerfully launch without a warning.</p>
<p>Steps to reproduce:</p>
<ol>
<li>Have existing, up-to-date Time Machine backups.</li>
<li>Delete a protocol handler.</li>
<li>Visit a web site that uses that protocol.</li>
</ol>
<p>Expected results:</p>
<ul>
<li>Mac OS X will respect that the application has been removed.</li>
</ul>
<p>Actual results:</p>
<ul>
<li>Mac OS X will hand it off to the application on the Time Machine backup volume.</li>
</ul>
<p>This seems to also be true of standard Finder document bindings. I tried double clicking a TextWrangler document after deleting TextWrangler and it cheerfully launched out of the Time Machine backup. Not that I think there’s anything wrong with TextWrangler; it was just a program I knew I could delete safely (and restore after).</p>
<p>It was pointed out to me on the <a href="http://www.macworld.com/forums/ubbthreads/showflat.php?Cat=0&amp;Number=547953">Macworld Forums</a> by Rob Griffiths that there is a way to permanently delete a file from all backups. You need to use the context menu within time machine to delete all backups of a file. This means there’s a workaround, but it’s still a problem that Mac OS X launches applications from the backup folder without even a warning.</p>
<p><strong>Update:</strong> Apparently, some don’t understand why this is a bug. Let me give you a simple example: You find out Adium (for example) has an available exploit that the developers haven’t patched yet. You remove Adium, but it continues to exist in your backup. You visit a web page that activates the Adium bug, and Adium is launched from your backup. That you can launch Adium from your backup is not a bug. That Mac OS X will do so <strong>automatically</strong> without confirmation is a bug. The backup should be considered a vault for the <strong>user</strong>, not Launch Services.</p>]]></content:encoded>
    </item>
    <item>
      <title>Leopard: First impressions</title>
      <link>https://tewha.net/2007/10/leopard-first-impressions/</link>
      <pubDate>Sat, 27 Oct 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/10/leopard-first-impressions/</guid>
      <description>&lt;p&gt;I used the default packages and install options because I haven’t seen my Office 2004 disc around in a while. The install was slow (I let it check the DVD), but required no intervention.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I used the default packages and install options because I haven’t seen my Office 2004 disc around in a while. The install was slow (I let it check the DVD), but required no intervention.</p>
<p>I thought Leopard’s menu bar was supposed to be ugly! I guess they’ve toned it down, because this looks pretty good to me. I’m not sold on the dock, but that’s okay: I know it can be <a href="http://forums.macrumors.com/showthread.php?referrerid=59552&amp;t=374120">turned off</a>.</p>
<p>Actually, if I had to describe it in three words, I’d say “System 7 modernized.” That’s a good thing. I thought Mac OS 8 was quite a step backwards, and Mac OS X has taken small but repeated steps back to the classic Mac look. Tiger is clean, with light backgrounds to its windows and a smooth gradient effect. Sheets are gorgeous.</p>
<p>My biggest complaint is that the window gradient is a little severe, especially on windows without toolbars. The dark end of the gradient is a little too dark.</p>
<p>Other random thoughts:</p>
<ul>
<li>Spotlight is reindexing. I’m not surprised.</li>
<li>System Preferences and Safari are really responsive. More so with Spotlight indexing in the background than they were in Tiger.</li>
<li>Quick Look is awesome. It would be nice if applications could launch this fast.</li>
<li>QuickVerse doesn’t work, but I’m pretty sure this isn’t a last minute Leopard change.</li>
</ul>
<p>I’ll post more thoughts after I have some time to really explore this.</p>]]></content:encoded>
    </item>
    <item>
      <title>Completely impossible isn’t.</title>
      <link>https://tewha.net/2007/10/completely-impossible-isnt/</link>
      <pubDate>Fri, 26 Oct 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/10/completely-impossible-isnt/</guid>
      <description>&lt;p&gt;An assertion is a check on a condition that you don’t expect to ever occur. These checks slow down the program, so they’re usually excluded from release builds. They’re often used in functions to check the parameters, entry and exit conditions.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>An assertion is a check on a condition that you don’t expect to ever occur. These checks slow down the program, so they’re usually excluded from release builds. They’re often used in functions to check the parameters, entry and exit conditions.</p>
<p>For instance, if you have your own sorted list class ((You shouldn’t. There are some great implementations of sorted lists, and thousands more poor ones. Guess which one you’ll probably write?)), you might do something like <code>assert(list_in_order())</code> as an entry condition on the search (because the list assumes it’s already sorted, and this should never be untrue), and <code>assert(list_in_order())</code> as an exit condition on the insert (because the list is trying to guarantee it will always be sorted).</p>
<p>Many months ago I thought of a simple assertion I could put in my application. I was redesigning a UI, and it had a progress bar. I briefly thought about adding a check to catch if the progress bar ever rolled backwards. But I decided against it, because it was so obviously impossible for it to occur. The reason? I’d have to add a miniscule amount of logic to actually keep track of the last progress bar value.</p>
<p>Yesterday we found a bug where the progress bar in our application rolled backwards. I fixed it, checked it in, and briefly remembered the assertion idea. “I wish I’d done that,” I thought to myself, “I would have found this a month ago!” I posted the next beta of the product and thought nothing more of it.</p>
<p>Today I found another case where the progress bar rolls backwards.</p>
<p>You know, that’s probably all I’m going to find. But this time I’ve put in the assertion. And I’m turning over a new leaf: from now on, I’ll really think about my entry and exit conditions and other flow assumptions, and make sure the code to verifies them. I was in that habit a few years ago in Pascal, but never really brought it over to C/C++.</p>]]></content:encoded>
    </item>
    <item>
      <title>First impressions of Final Cut Pro</title>
      <link>https://tewha.net/2007/10/first-impressions-of-final-cut-pro/</link>
      <pubDate>Thu, 25 Oct 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/10/first-impressions-of-final-cut-pro/</guid>
      <description>&lt;p&gt;Today I spent my evening helping a friend figure out how to burn DVDs from video he put together in Final Cut Pro. He’s a Mac neophyte, and not really a techie guy in general.&lt;/p&gt;
&lt;p&gt;This was my first time working with Final Cut Pro.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Today I spent my evening helping a friend figure out how to burn DVDs from video he put together in Final Cut Pro. He’s a Mac neophyte, and not really a techie guy in general.</p>
<p>This was my first time working with Final Cut Pro.</p>
<p>The Bad: The interface is just plain weird. It isn’t very attractive for one thing: The blue-grey reminded me of a submarine. But that’s just the start of it. The widgets are absurdly small even on windows that didn’t need small absurdly widgets. There’s no reason that a “Batch Start” widget should be shorter than Aqua’s close widgets!</p>
<p>Everything was just nonstandard looking, and (worse) nonstandard behaving.Final Cut Pro is an absurdly complicated program, so complexity is expected, but it hasn’t hit the sweet spot. The interface feels like it could have half the complexity while still having all the features.</p>
<p>The Good: Resizable scroll bars. Grabbing the top edge of the scroll car and dragging it up zooms out. This probably sounds weird, but it’s really just the inverse of proportional scrollbars. With proportional scroll bars, as you see more of the document the scroll car gets bigger. With Final Cut’s scroll bars, as you make the scroll car bigger you zoom out to see more of the document. I’d love to have these in many Mac OS X applications.</p>
<p>The main video editing window seems perfectly reasonable, too. I didn’t have a lot of time to try this out.</p>]]></content:encoded>
    </item>
    <item>
      <title>A brief conversation on web standards</title>
      <link>https://tewha.net/2007/10/a-brief-conversation-on-web-standards/</link>
      <pubDate>Tue, 23 Oct 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/10/a-brief-conversation-on-web-standards/</guid>
      <description>&lt;p&gt;“I’ve got to figure out why he used ALIGN, despite it being deprecated since 1999.”&lt;/p&gt;
&lt;p&gt;“ALIGN the tag or the attribute?”&lt;/p&gt;
&lt;p&gt;“The tag.”&lt;/p&gt;
&lt;p&gt;“Wasn’t it introduced in 1998?”&lt;/p&gt;
&lt;p&gt;“No, it was introduced in 1995. It wasn’t &lt;em&gt;supported&lt;/em&gt; until 1998.”&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>“I’ve got to figure out why he used ALIGN, despite it being deprecated since 1999.”</p>
<p>“ALIGN the tag or the attribute?”</p>
<p>“The tag.”</p>
<p>“Wasn’t it introduced in 1998?”</p>
<p>“No, it was introduced in 1995. It wasn’t <em>supported</em> until 1998.”</p>
]]></content:encoded>
    </item>
    <item>
      <title>↩ in URLs</title>
      <link>https://tewha.net/2007/10/%E2%86%A9-in-urls/</link>
      <pubDate>Fri, 19 Oct 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/10/%E2%86%A9-in-urls/</guid>
      <description></description>
      <content:encoded><![CDATA[<p>Watching the log, though, I find one thing interesting:</p>
<pre><code>[19/Oct/2007:12:12:37 -0700] &quot;GET /wp-content/themes/pyilewptheme/iphone.css HTTP/1.1&quot; 200 355 &quot;http://pyile.com/2007/10/i-want-my-%e2%86%a9/&quot; &quot;Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/419.3 (KHTML, like Gecko) Safari/419.3&quot;

[19/Oct/2007:12:12:37 -0700] &quot;GET /wp-content/themes/pyilewptheme/iphone.css HTTP/1.1&quot; 200 354 &quot;http://pyile.com/2007/10/i-want-my-%E2%86%A9/&quot; &quot;Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.5) Gecko/20070718 Firefox/2.0.0.5&quot;
</code></pre>
<p>It looks like Safari and Firefox encode the ↩ differently in URLs. I’m not sure which, if either, is “wrong ((I’m sure it’s in the HTTP spec, but I can’t be bothered looking it up right now.)),” but I found this interesting. When I was testing the ↩ in the URL, I only checked that it <strong>worked</strong> in Firefox and Safari. I didn’t think to check that they requested it the same way. I imagine Apache is doing the conversion here, but would other web servers do it as well?</p>]]></content:encoded>
    </item>
    <item>
      <title>I want my ↩!</title>
      <link>https://tewha.net/2007/10/i-want-my-%E2%86%A9/</link>
      <pubDate>Thu, 18 Oct 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/10/i-want-my-%E2%86%A9/</guid>
      <description>&lt;p&gt;Curiously, the iPhone and iPod touch are &lt;a href=&#34;http://equinox-of-insanity.com/2007/07/iphone-fonts-and-missing-glyphs&#34;&gt;missing the ↩&lt;/a&gt; glyph ((If you see a box it’s still missing)). I’m sure it’s missing because Apple never thought anyone would use it, but it’s being used as a footnote return character by &lt;a href=&#34;http://daringfireball.net&#34;&gt;John Gruber&lt;/a&gt;, &lt;a href=&#34;http://www.antipode.ca&#34;&gt;Allen Pike&lt;/a&gt; and &lt;a href=&#34;http://warpedvisions.org&#34;&gt;mx&lt;/a&gt;, among thousands ((ten thousands?)) more.&lt;/p&gt;
&lt;p&gt;Apple does respond to feedback, so it’s worth asking. If you’ve got an iPod touch, file feedback &lt;a href=&#34;http://www.apple.com/feedback/ipodtouch.html&#34;&gt;here&lt;/a&gt;. If you’ve got an iPhone, the feedback site is &lt;a href=&#34;http://www.apple.com/feedback/iphone.html&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Curiously, the iPhone and iPod touch are <a href="http://equinox-of-insanity.com/2007/07/iphone-fonts-and-missing-glyphs">missing the ↩</a> glyph ((If you see a box it’s still missing)). I’m sure it’s missing because Apple never thought anyone would use it, but it’s being used as a footnote return character by <a href="http://daringfireball.net">John Gruber</a>, <a href="http://www.antipode.ca">Allen Pike</a> and <a href="http://warpedvisions.org">mx</a>, among thousands ((ten thousands?)) more.</p>
<p>Apple does respond to feedback, so it’s worth asking. If you’ve got an iPod touch, file feedback <a href="http://www.apple.com/feedback/ipodtouch.html">here</a>. If you’ve got an iPhone, the feedback site is <a href="http://www.apple.com/feedback/iphone.html">here</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>How not to do a 30 day trial</title>
      <link>https://tewha.net/2007/09/how-not-to-do-a-30-day-trial/</link>
      <pubDate>Fri, 07 Sep 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/09/how-not-to-do-a-30-day-trial/</guid>
      <description>&lt;p&gt;Well, I downloaded the trial of &lt;a href=&#34;http://www.e-texteditor.com/&#34;&gt;e&lt;/a&gt;, a poorly named but apparently quite capable text editor for Windows. It was a 1.0 release and not very stable, so I uninstalled it on the first day I had it and waited for an update. I downloaded the update yesterday to discover&lt;/p&gt;
&lt;p&gt;The trial has 2 days remaining.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Well, I downloaded the trial of <a href="http://www.e-texteditor.com/">e</a>, a poorly named but apparently quite capable text editor for Windows. It was a 1.0 release and not very stable, so I uninstalled it on the first day I had it and waited for an update. I downloaded the update yesterday to discover</p>
<p>The trial has 2 days remaining.</p>
<p>That’s really all I needed to see. I immediately uninstalled it. e might very well be great software, but since I never really got to try it the developer is not going to get a purchase from me.</p>
<p>Anyone doing a time limited trial needs to seriously consider how it expires. This kind of 30 day trial doesn’t give me a chance to evaluate the software, and it doesn’t give the developer any chance to make a sale. The developer would be much better off using 30 days of use (like <a href="http://www.omnigroup.com/">Omni Group</a> products), or reseting the trial when the software is reinstalled, or even just resetting the trial for new releases. How many months in a row do you think someone’s going to do an unnecessary uninstall/reinstall just to avoid paying a reasonable $34.95?</p>
<p>Anyway, that’s all the feedback I have from a 30 day trial. Sad, isn’t it?</p>]]></content:encoded>
    </item>
    <item>
      <title>Windows Installers made… less painful</title>
      <link>https://tewha.net/2007/08/windows-installers-made-less-painful/</link>
      <pubDate>Wed, 15 Aug 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/08/windows-installers-made-less-painful/</guid>
      <description>&lt;p&gt;Let’s face it, deploying an application on Windows is never fun. We’ve been using WiX, which is about as unfun as one can possibly get. I actually think the exact number is slightly higher than this, but I’ve gotten used to saying “1,200 lines of XML to install 7 files.” Not a big deal, until you have several components needing separate installers.&lt;/p&gt;
&lt;p&gt;Adding XML to a problem means you have two problems: The original problem, plus XML.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Let’s face it, deploying an application on Windows is never fun. We’ve been using WiX, which is about as unfun as one can possibly get. I actually think the exact number is slightly higher than this, but I’ve gotten used to saying “1,200 lines of XML to install 7 files.” Not a big deal, until you have several components needing separate installers.</p>
<p>Adding XML to a problem means you have two problems: The original problem, plus XML.</p>
<p>Visual Studio 2005 has a much better installer system built into it, though, called Windows Setup.</p>
<p>The first few times I tried it, I quickly moved on because it popped up a installer dialog. It turns out I just needed more patience: After several minutes of waiting, it asked for the Visual Studio CD and installed the components it needed. And that was that. The installer popping up to build an installer wasn’t a daily stupidity, just a one-time thing.</p>
<p>The tool is (comparatively) a joy to use, using Visual Studio editors and the property inspectors. Better, it deals with dependencies in a way that only someone with direct access to the idiot that designed the system could manage. I still don’t fully understand what the installer is doing, but I find that I don’t really care: It works, and works well. I can’t imagine going back to WiX at this point.</p>]]></content:encoded>
    </item>
    <item>
      <title>Q-XPACK 2</title>
      <link>https://tewha.net/2007/08/q-xpack-2/</link>
      <pubDate>Fri, 03 Aug 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/08/q-xpack-2/</guid>
      <description>&lt;p&gt;I bought a Apevia Q-XPACK 2 of these as a replacement to a Q-XPACK (i.e., the first model). Was pleasantly surprised to find a lot of the hardware is exactly the same as the Q-XPACK: motherboard tray, drive assembly. Install was really fast as a result. The sides/top of the case is the same size as the Q-XPACK, although I think the Q-XPACK’s is a little sturdier. I bought a refurb with sharp gouge on the outer case, so I just used my old wrapper.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I bought a Apevia Q-XPACK 2 of these as a replacement to a Q-XPACK (i.e., the first model). Was pleasantly surprised to find a lot of the hardware is exactly the same as the Q-XPACK: motherboard tray, drive assembly. Install was really fast as a result. The sides/top of the case is the same size as the Q-XPACK, although I think the Q-XPACK’s is a little sturdier. I bought a refurb with sharp gouge on the outer case, so I just used my old wrapper.</p>
<p>The extra inch of depth is mostly in the front of the case and in how the parts fit within the assembly. The design is nicer than it looks in photos. Fan LED is definitely much brighter than the Q-XPACK. How much brighter? Well, my next purchase is probably going to be a fan.</p>
<p>Lack of power cable management is one downside here. The cables are wired directly into the power supply, so unless you’re willing to cut them you’re probably going to end up with at least one that you’re not using. That’s pretty typical, but it hurts a little more here; There’s more cables than the Q-XPACK, and not much space to hide them away.</p>
<p>Of course, it’s much too early to see how the power supply stands up.</p>
<p>I was very pleased with the Q-XPACK right up until the power supply started wavering. The Q-XPACK2 seems to have everything I liked about the Q-XPACK, plus the (theoretically) more robust and standard power supply. Even if the power supply isn’t as robust as I’m expecting, being able to swap it is a major benefit.</p>
<p>Other problems? Well, this was a refurb, and it had some problems from that. The handle wasn’t very well attached, and it didn’t come with a couple cables that it should have. Neither of these was a problem for me, though.</p>]]></content:encoded>
    </item>
    <item>
      <title>Domain names</title>
      <link>https://tewha.net/2007/05/domain-names/</link>
      <pubDate>Sat, 26 May 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/05/domain-names/</guid>
      <description>&lt;p&gt;When I registered objectsatrest.com in 2004, I had a specific goal in mind. I wanted to create musical software, and I was commuting between Canada and the Philippines every few months. The name appealed to me because of the double meaning: Musical rest, and traveling. In time, I wanted to start a blog, and it became objectsatrest.com more out of default than anything else.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>When I registered objectsatrest.com in 2004, I had a specific goal in mind. I wanted to create musical software, and I was commuting between Canada and the Philippines every few months. The name appealed to me because of the double meaning: Musical rest, and traveling. In time, I wanted to start a blog, and it became objectsatrest.com more out of default than anything else.</p>
<p>Years later, the desire to be able to write software independent of the company I work for arose in me again. But where? I still liked the objectsatrest name, even if it seemed I wasn’t likely to do musical software again. So I moved my blog to a new domain name I’d just registered and started thinking about the site.</p>
<p>In moving, I attracted the attention of the owner of objectsatrest.org, who wanted to upgrade to the .com domain if possible. Was I interested in selling?</p>
<p>It wasn’t an easy decision. For years, objectsatrest.com had been my online identity. I’d gotten used to thinking it. I think I’ve typed “Objects At Rest” a thousand times since 2004.</p>
<p>In the end, we came to a deal. Objects At Rest now belongs to Objects At Rest Animation Studios. Man, that’s <em>almost</em> as good a reason for the name as I had, and a better reason than I had when I sold!</p>]]></content:encoded>
    </item>
    <item>
      <title>Qt part 1: Project configuration</title>
      <link>https://tewha.net/2007/03/qt-part-1-project-configuration/</link>
      <pubDate>Tue, 27 Mar 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/03/qt-part-1-project-configuration/</guid>
      <description>&lt;p&gt;We develop applications for multiple platforms here. How to do this is something of a challenge; in the past, I’ve favored writing custom interfaces and using common business logic. To be blunt, I still think this makes a lot of sense, although in the past we’ve made some choices as to the various languages to write things in that turned out pretty poorly over the years.&lt;/p&gt;
&lt;p&gt;Another developer here suggested we evaluate Qt. To make a long story short, we’ve placed an order and plan to use it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>We develop applications for multiple platforms here. How to do this is something of a challenge; in the past, I’ve favored writing custom interfaces and using common business logic. To be blunt, I still think this makes a lot of sense, although in the past we’ve made some choices as to the various languages to write things in that turned out pretty poorly over the years.</p>
<p>Another developer here suggested we evaluate Qt. To make a long story short, we’ve placed an order and plan to use it.</p>
<h2 id="project_configuration_made_easy">Project configuration made easy.</h2>
<p>Qt’s cross platform abstraction starts with the project file. For instance, a trivial QT project file might look like this:</p>
<pre><code>TEMPLATE = app
SOURCES += main.cpp
</code></pre>
<p>Type qmake on the Mac and it’s converted to a Project Builder or Xcode project. I believe makefiles are supported on Mac, too, but I haven’t tried that yet. Import it into Visual Studio with Qt’s Visual Studio integration and it becomes a vcproj.</p>
<p>Want to add precompiled headers and make it a debug build?</p>
<pre><code>CONFIG +=debug
PRECOMPILED_HEADER = stable.h
</code></pre>
<p>(This assumes that stable.h #includes your headers that aren’t going to change.)</p>
<p>Run qmake again on the host platform (or import into Visual Studio), and the project file will be regenerated to use stable.h as a precompiled header and we’re using debug libraries and appropriate settings.</p>
<p>Want a universal build on the Mac?</p>
<pre><code>QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.4u.sdk
CONFIG +=x86 ppc
</code></pre>
<p>Want to build a Visual Studio project? Move over to Visual Studio 2005 and choose <strong>Open Solution from .pro File</strong>. A second later, you’re looking at a Visual Studio project with the equivalent configuration.</p>
<p>It really is that easy. The difficulty is in finding the variable names, and that’s documented on TrollTech’s website.</p>]]></content:encoded>
    </item>
    <item>
      <title>Comparing Mac Minis to PowerBooks</title>
      <link>https://tewha.net/2007/03/comparing-mac-minis-to-powerbooks/</link>
      <pubDate>Thu, 15 Mar 2007 07:00:00 +0000</pubDate>
      <guid>https://tewha.net/2007/03/comparing-mac-minis-to-powerbooks/</guid>
      <description>&lt;p&gt;I’ve been frustrated lately by slow build times on my mini. I found out why a few days ago, and have been from time to time adding a few notes to a draft article. The time has come to declare the article done&lt;/p&gt;
&lt;p&gt;An Xcode build on my personal PowerBook (it has 768MB of RAM), with a bunch of applications open:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I’ve been frustrated lately by slow build times on my mini. I found out why a few days ago, and have been from time to time adding a few notes to a draft article. The time has come to declare the article done</p>
<p>An Xcode build on my personal PowerBook (it has 768MB of RAM), with a bunch of applications open:</p>
<p>VM: 5.81G +  150M   220631(1) pageins, 60523(0) pageouts</p>
<p>The highest number I saw there was about 200, and it appeared only once or twice. The vast majority of the build, it was 0.</p>
<p>An Xcode build on the Intel Mac Mini (it has 512MB of RAM), with only Finder and Xcode running:</p>
<pre><code>VM: 8.93G + 7.19M   760989(93) pageins, 277742(22) pageouts
</code></pre>
<p>The highest number I saw was 3,180. Usually, it hovered around 100-200, with occasional drops to 0 depending on the phase the build was in.</p>
<p>There’s a couple obvious points here:</p>
<ul>
<li>The mini is doing at least one order of magnitude more swapping than the PowerBook. The total pageins don’t reflect that the PowerBook has seen much heavier use since the last restart, but that’s irrelevant to the recent pageins. More pageins is to expected; after all, the mini has less memory.</li>
<li>The mini is using <em>much</em> more VM to accomplish less than the PowerBook. This I didn’t expect. The PowerBook is running more applications and is even using a FileVault-encrypted home directory. The mini, on the other hand, is as bare as I could get it without wasting time on it.</li>
</ul>]]></content:encoded>
    </item>
  </channel>
</rss>
