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

<channel>
	<title>Tewha</title>
	<atom:link href="http://tewha.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://tewha.net</link>
	<description>Writings and links on iPhone and iPad programming</description>
	<lastBuildDate>Fri, 27 Jan 2012 07:58:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>I&#8217;ve changed my mind about Xcode snapshots</title>
		<link>http://tewha.net/2012/01/ive-changed-my-mind-about-xcode-snapshots/</link>
		<comments>http://tewha.net/2012/01/ive-changed-my-mind-about-xcode-snapshots/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 05:08:13 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[hubris]]></category>
		<category><![CDATA[snapshots]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1244</guid>
		<description><![CDATA[In the recent past, I&#8217;ve mocked Xcode&#8217;s snapshots. They were sluggish and not especially reliable. I&#8217;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 &#8230; <a href="http://tewha.net/2012/01/ive-changed-my-mind-about-xcode-snapshots/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the recent past, <a href="/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots">I&#8217;ve mocked Xcode&#8217;s snapshots</a>. They were sluggish and not especially reliable. I&#8217;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&#8217;m not sure when they really improved, but in the most recent build of Xcode they take 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&#8217;re pretty efficient, too. This does <strong>not</strong> affect your real <code>git</code> repository, even if you&#8217;re using <code>git</code>. This is entirely separate, deep in Xcode&#8217;s private directory tree deep in your home folder.</p>

<p>Xcode can run a behaviour when a build succeeds. I noticed a few days ago that there&#8217;s also an option to <strong>Create snapshot</strong>.</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&#8217;ll be in a refactor and I won&#8217;t be committing every time the project builds. I&#8217;ll make a few changes, build and fix any errors, make a few more changes. I&#8217;ll keep this up several times, until I&#8217;ve made the full refactor I want. Only then will I fully test what I&#8217;ve done and commit.</p>

<p>Sometimes I&#8217;ll make the wrong change, and break the build in ways I can&#8217;t easily fix. At that point, I either need to struggle my way out of the errors I&#8217;ve introduced or abandon all the changes I&#8217;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&#8217;re offered before major but atomic changes, which is right after I&#8217;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&#8217;m thrilled this feature exists, and I&#8217;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&#8217;t think to, and without any action on your part.</p>
]]></content:encoded>
			<wfw:commentRss>http://tewha.net/2012/01/ive-changed-my-mind-about-xcode-snapshots/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How the iPhone GPS differs from a standalone navigation GPS</title>
		<link>http://tewha.net/2011/10/how-the-iphone-gps-differs-from-a-standalone-navigation-gps/</link>
		<comments>http://tewha.net/2011/10/how-the-iphone-gps-differs-from-a-standalone-navigation-gps/#comments</comments>
		<pubDate>Sat, 29 Oct 2011 19:28:54 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[AGPS]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[navigation]]></category>
		<category><![CDATA[WiFi]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1240</guid>
		<description><![CDATA[All models of iPhone since the 3G, as well as the iPad 3G and iPad 2 3G, include Assisted GPS (AGPS). I&#8217;ve heard that this isn&#8217;t real GPS or that it&#8217;s somehow inferior to real GPS. AGPS is actually superior &#8230; <a href="http://tewha.net/2011/10/how-the-iphone-gps-differs-from-a-standalone-navigation-gps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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&#8217;ve heard that this isn&#8217;t real GPS or that it&#8217;s somehow inferior to real GPS. AGPS is actually superior to &#8220;real&#8221; GPS. However, there are ways the iPhone is also inferior to a standalone navigational GPS like a Garmin or Tom Tom. I&#8217;m going to explain the differences between them.</p>

<h2>Positioning</h2>

<p>The iPhone includes a regular GPS receiver, just like your standalone GPS. The &#8220;assisted&#8221; 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&#8217;m not going to try to write an explanation of this. There&#8217;s a great article on this in Macworld by Glenn Fleishman, &#8220;<a href="https://www.macworld.com/article/159528/2011/04/how_iphone_location_works.html">How the iPhone knows where you are</a>,&#8221; which you should read. He&#8217;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&#8217;t bother to read it:</p>

<p>Because the iPhone has a GPS radio <em>and</em> these other data sources, it&#8217;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&#8217;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&#8217;s capable of. But when you need accurate positioning, it&#8217;s there.</p>

<h2>Maps</h2>

<p>So why do people think the iPhone&#8217;s GPS isn&#8217;t a real GPS? It&#8217;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="http://tewha.net/wp-content/uploads/2011/10/IMG_0002.png" alt="" title="No map data" width="160" height="240" class="alignnone size-medium wp-image-1241"></p>

<p>From this, you might conclude that without a data connection your iPhone isn&#8217;t very good as a navigational tool. You&#8217;d be right about that! But you might also conclude that the iPhone doesn&#8217;t know where you are. In fact, it knows where you are. It just isn&#8217;t able to put it on a map, because it doesn&#8217;t actually have a map of the area.</p>

<p>This is where standalone GPS devices are better. Because they don&#8217;t have the extra radios that the iPhone has, they can&#8217;t download map data from the Internet. Instead, a standalone GPS includes map data on the device. Storing an entire country&#8217;s (or even an entire continent&#8217;s) map data takes a lot of space, so it&#8217;s often rendered more crudely than the iPhone&#8217;s maps.</p>

<p>Imagine drawing a map for a friend to get to your house. You know which road they&#8217;ll be coming on, and you know where they&#8217;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&#8217;s up-to-date it knows <strong>all</strong> the roads and can quickly draw everything quickly and to scale. It&#8217;s rendered using just its memory, without the aid of a 3G or WiFi network.</p>

<p>The iPhone&#8217;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&#8217;s interested in. The image the cloud returns can be beautifully rendered and completely up-to-date, but without the cloud, the iPhone can&#8217;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>Turn-by-turn navigation</h2>

<p>If you&#8217;ve reached this point, you&#8217;re probably wondering why the iPhone can&#8217;t do turn-by-turn navigation. It&#8217;s a fair question. The answer is complicated, but boils down simply: Apple does not provide the map data. Instead, Apple&#8217;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&#8217;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&#8217;s available. There&#8217;s been a few hints that Apple may switch to their own data at some point, but it hasn&#8217;t happened yet. Being dependent on a competitor interested in keeping your device inferior isn&#8217;t a good position to be in, even if the reasoning has nothing to do with competition.</p>

<h2>Conclusion</h2>

<p>The iPhone&#8217;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&#8217;s a complicated tradeoff. Saying the iPhone does not have &#8220;real&#8221; GPS or that AGPS is not &#8220;real&#8221;, though, is inaccurate.</p>
]]></content:encoded>
			<wfw:commentRss>http://tewha.net/2011/10/how-the-iphone-gps-differs-from-a-standalone-navigation-gps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dennis Ritchie</title>
		<link>http://tewha.net/2011/10/dennis-ritchie/</link>
		<comments>http://tewha.net/2011/10/dennis-ritchie/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 18:05:29 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1239</guid>
		<description><![CDATA[Dennis Ritchie, creator of the C programming language, has died at age 70. This soon after my post on Steve Jobs, I&#8217;m unable to write much on the subject. But the C programming language was a major invention in the &#8230; <a href="http://tewha.net/2011/10/dennis-ritchie/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><span class="Apple-style-span" style="font-style: normal;"><a href="http://herbsutter.com/2011/10/12/dennis-ritchie/">Dennis Ritchie</a>, creator of the C programming language, has died at age 70.</span></p>

<p>This soon after my post on Steve Jobs, I&#8217;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>
			<wfw:commentRss>http://tewha.net/2011/10/dennis-ritchie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Steve Jobs shaped my life</title>
		<link>http://tewha.net/2011/10/steve-jobs-shaped-my-life/</link>
		<comments>http://tewha.net/2011/10/steve-jobs-shaped-my-life/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 06:41:28 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1236</guid>
		<description><![CDATA[I never met Steve Jobs. I&#8217;ve never even been in the same room as him, or (to my knowledge), the same city. So why am I choked up about his death? Because I love the man for what he accomplished, &#8230; <a href="http://tewha.net/2011/10/steve-jobs-shaped-my-life/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I never met Steve Jobs. I&#8217;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&#8217;s changed the world.</p>

<p>Way back in elementary school, I used an Apple //e. I moved Logo&#8217;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&#8217;t actually magic, it just felt like it. I didn&#8217;t know it at the time, but Steve Jobs had made that experience happen. He didn&#8217;t write the code, and exactly how much of the design was his I&#8217;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&#8217;t what I yearned to build. It wasn&#8217;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&#8217;t get this, but that wasn&#8217;t the case at all. If anything, just the opposite: these machines were far more hostile than I was willing to admit. I couldn&#8217;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&#8217;t last. I knew we were going backwards again, but I didn&#8217;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&#8243; cut of it. Again, that was Steve Jobs. Not solely responsible. I don&#8217;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&#8217;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&#8217;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&#8217;re worth building.</li>
<li>Great things can achieved, even under pressure from others who don&#8217;t see the same future.</li>
<li>Greatness is revolutionary, but does not ignore what&#8217;s gone before.</li>
<li>It&#8217;s okay to not achieve perfection. Producing something amazing is good enough.</li>
<li>Having achieved something amazing, there&#8217;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&#8217;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&#8217;s only true if we don&#8217;t create more of our own.</p>
]]></content:encoded>
			<wfw:commentRss>http://tewha.net/2011/10/steve-jobs-shaped-my-life/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An imaginary conversation with Xcode 4 regarding snapshots</title>
		<link>http://tewha.net/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots/</link>
		<comments>http://tewha.net/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 20:05:13 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[venting]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1235</guid>
		<description><![CDATA[Xcode: Hey… Me: Yeah? Xcode: You want to enable snapshots yet? Me: No. Xcode: I&#8217;m just asking. Me: No. Xcode: They&#8217;re good for you, you know. Me: I&#8217;m sure they are, but see, I&#8217;ve already backed up my project. In &#8230; <a href="http://tewha.net/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Xcode: Hey…</p>

<p>Me: Yeah?</p>

<p>Xcode: You want to enable snapshots yet?</p>

<p>Me: No.</p>

<p>Xcode: I&#8217;m just asking.</p>

<p>Me: No.</p>

<p>Xcode: They&#8217;re good for you, you know.</p>

<p>Me: I&#8217;m sure they are, but see, I&#8217;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&#8217;ve caught you at a bad time.</p>

<p>Me: That&#8217;s not it. I don&#8217;t actually <strong>want</strong> snapshots. They&#8217;re redundant, and frankly a bit stupid. It makes me feel like you don&#8217;t respect me enough to make my own backups, you know?</p>

<p>Xcode: Oh. I can see that. I&#8217;ll ask again later, then.</p>
]]></content:encoded>
			<wfw:commentRss>http://tewha.net/2011/09/an-imaginary-conversation-with-xcode-4-regarding-snapshots/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Objective-C memory management</title>
		<link>http://tewha.net/2011/08/objective-c-memory-management/</link>
		<comments>http://tewha.net/2011/08/objective-c-memory-management/#comments</comments>
		<pubDate>Sun, 21 Aug 2011 21:34:37 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[memory management]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1232</guid>
		<description><![CDATA[With Automatic Reference Counting (ARC) coming out soon, you could argue this post is coming almost too late. But there&#8217;s a lot of confusion over this, and I don&#8217;t think ARC will help much if you don&#8217;t understand the why &#8230; <a href="http://tewha.net/2011/08/objective-c-memory-management/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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&#8217;s a lot of confusion over this, and I don&#8217;t think ARC will help much if you don&#8217;t understand the <em>why</em> of memory management.</p>

<p>After a couple years, I&#8217;ve come to adopt some very simple rules for memory management.</p>

<h2>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&#8217;re doing, rather than the <em>what</em>. After you&#8217;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>&#8216;s delegate or data source.</li>
</ul>

<h2>Practical guidelines</h2>

<p>But how does this translate to code? There&#8217;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&#8217;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&#8217;s value except in the property&#8217;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&#8217;re doing too much. (And, also, you&#8217;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&#8217;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&#8217;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&#8217;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&#8217;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>
			<wfw:commentRss>http://tewha.net/2011/08/objective-c-memory-management/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to reset Wii to  lower resolution</title>
		<link>http://tewha.net/2011/08/how-to-reset-wii-to-lower-resolution/</link>
		<comments>http://tewha.net/2011/08/how-to-reset-wii-to-lower-resolution/#comments</comments>
		<pubDate>Sun, 07 Aug 2011 00:27:52 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[480i]]></category>
		<category><![CDATA[480p]]></category>
		<category><![CDATA[nintendo]]></category>
		<category><![CDATA[nintendo wii]]></category>
		<category><![CDATA[troubleshooting]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1167</guid>
		<description><![CDATA[So you&#8217;ve set your Wii to 480p, then moved it back to a TV that supports only 480i. How do you fix it? I searched for this for a while and found a few wrong and complicated answers. One way &#8230; <a href="http://tewha.net/2011/08/how-to-reset-wii-to-lower-resolution/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>So you&#8217;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&#8217;re only using 480i the component cable does nothing extra for you anyway.</p>

<p>But what if you can&#8217;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&#8217;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>
			<wfw:commentRss>http://tewha.net/2011/08/how-to-reset-wii-to-lower-resolution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blocks to remove redundancy</title>
		<link>http://tewha.net/2011/07/blocks-to-remove-redundancy/</link>
		<comments>http://tewha.net/2011/07/blocks-to-remove-redundancy/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 15:25:56 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[blocks]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[objective-c]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1166</guid>
		<description><![CDATA[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. Here&#8217;s a common operation for me: Split a list into sublists based on &#8230; <a href="http://tewha.net/2011/07/blocks-to-remove-redundancy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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&#8217;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&#8217;s left into another sublist.</p>

<p>Without blocks, this looks like this:</p>

<div class="highlight-wrapper objc">
<div class="tools">
<div class="wrap">
<a href="#" class="about">?</a><div class="clear"></div>
</div>
<div class="clear"></div>
</div>
<pre class="raw"><code lang="objc">
- (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], @"Records",
                              label, @"Name",
                              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], @"Records",
                      label, @"Name",
                      nil];
        [sections addObject: section];
        [sectionRecords removeAllObjects];
    }
    
    return [NSArray arrayWithArray: sections];
}
</code></pre>
<div class="highlighted"><table class="highlighttable"><tr>
<td class="linenos"><div class="linenodiv"><pre class="nl"> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38</pre></div></td>
<td class="code">
<div class="highlight"><pre><span class="o">-</span> <span class="p">(</span><span class="n">NSArray</span> <span class="o">*</span><span class="p">)</span><span class="nl">splitArray:</span> <span class="p">(</span><span class="n">NSArray</span> <span class="o">*</span><span class="p">)</span><span class="n">array</span>
               <span class="nl">valueKey:</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="n">valueKey</span>
               <span class="nl">labelKey:</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="n">labelKey</span><span class="p">;</span>
<span class="p">{</span>
    <span class="kt">id</span> <span class="n">sections</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSMutableArray</span> <span class="n">array</span><span class="p">];</span>
    <span class="kt">id</span> <span class="n">sectionValue</span> <span class="o">=</span> <span class="nb">nil</span><span class="p">;</span>
    <span class="kt">id</span> <span class="n">sectionRecords</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSMutableArray</span> <span class="n">array</span><span class="p">];</span>
    
    <span class="k">for</span> <span class="p">(</span><span class="kt">id</span> <span class="n">record</span> <span class="k">in</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">id</span> <span class="n">recordValue</span> <span class="o">=</span> <span class="p">[</span><span class="n">record</span> <span class="nl">objectForKey:</span> <span class="n">valueKey</span><span class="p">];</span>
        <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="p">[</span><span class="n">recordValue</span> <span class="nl">isEqual:</span> <span class="n">sectionValue</span><span class="p">]</span> <span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span> <span class="p">[</span><span class="n">sectionRecords</span> <span class="n">count</span><span class="p">]</span> <span class="p">)</span> <span class="p">{</span>
                <span class="kt">id</span> <span class="n">lastRecord</span> <span class="o">=</span> <span class="p">[</span><span class="n">sectionRecords</span> <span class="nl">objectAtIndex:</span> <span class="mi">0</span><span class="p">];</span>
                <span class="kt">id</span> <span class="n">label</span> <span class="o">=</span> <span class="p">[</span><span class="n">lastRecord</span> <span class="nl">objectForKey:</span> <span class="n">labelKey</span><span class="p">];</span>
                <span class="kt">id</span> <span class="n">section</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSDictionary</span> <span class="nl">dictionaryWithObjectsAndKeys:</span>
                              <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithArray:</span> <span class="n">sectionRecords</span><span class="p">],</span> <span class="s">@"Records"</span><span class="p">,</span>
                              <span class="n">label</span><span class="p">,</span> <span class="s">@"Name"</span><span class="p">,</span>
                              <span class="nb">nil</span><span class="p">];</span>
                <span class="p">[</span><span class="n">sections</span> <span class="nl">addObject:</span> <span class="n">section</span><span class="p">];</span>
                <span class="p">[</span><span class="n">sectionRecords</span> <span class="n">removeAllObjects</span><span class="p">];</span>
            <span class="p">}</span>
            <span class="n">sectionValue</span> <span class="o">=</span> <span class="n">recordValue</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="p">[</span><span class="n">sectionRecords</span> <span class="nl">addObject:</span> <span class="n">record</span><span class="p">];</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">(</span> <span class="p">[</span><span class="n">sectionRecords</span> <span class="n">count</span><span class="p">]</span> <span class="p">)</span> <span class="p">{</span>
        <span class="kt">id</span> <span class="n">lastRecord</span> <span class="o">=</span> <span class="p">[</span><span class="n">sectionRecords</span> <span class="nl">objectAtIndex:</span> <span class="mi">0</span><span class="p">];</span>
        <span class="kt">id</span> <span class="n">label</span> <span class="o">=</span> <span class="p">[</span><span class="n">lastRecord</span> <span class="nl">objectForKey:</span> <span class="n">labelKey</span><span class="p">];</span>
        <span class="kt">id</span> <span class="n">section</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSDictionary</span> <span class="nl">dictionaryWithObjectsAndKeys:</span>
                      <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithArray:</span> <span class="n">sectionRecords</span><span class="p">],</span> <span class="s">@"Records"</span><span class="p">,</span>
                      <span class="n">label</span><span class="p">,</span> <span class="s">@"Name"</span><span class="p">,</span>
                      <span class="nb">nil</span><span class="p">];</span>
        <span class="p">[</span><span class="n">sections</span> <span class="nl">addObject:</span> <span class="n">section</span><span class="p">];</span>
        <span class="p">[</span><span class="n">sectionRecords</span> <span class="n">removeAllObjects</span><span class="p">];</span>
    <span class="p">}</span>
    
    <span class="k">return</span> <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithArray:</span> <span class="n">sections</span><span class="p">];</span>
<span class="p">}</span>
</pre></div>
</td>
</tr></table></div>
</div>

<p>The redundancy makes this hard to maintain, but I don&#8217;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>

<div class="highlight-wrapper objc">
<div class="tools">
<div class="wrap">
<a href="#" class="about">?</a><div class="clear"></div>
</div>
<div class="clear"></div>
</div>
<pre class="raw"><code lang="objc">
- (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], @"Records",
                          label, @"Name",
                          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>
<div class="highlighted"><table class="highlighttable"><tr>
<td class="linenos"><div class="linenodiv"><pre class="nl"> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33</pre></div></td>
<td class="code">
<div class="highlight"><pre><span class="o">-</span> <span class="p">(</span><span class="n">NSArray</span> <span class="o">*</span><span class="p">)</span><span class="nl">splitArray:</span> <span class="p">(</span><span class="n">NSArray</span> <span class="o">*</span><span class="p">)</span><span class="n">array</span>
               <span class="nl">valueKey:</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="n">valueKey</span>
               <span class="nl">labelKey:</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="n">labelKey</span><span class="p">;</span>
<span class="p">{</span>
    <span class="kt">id</span> <span class="n">sections</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSMutableArray</span> <span class="n">array</span><span class="p">];</span>
    <span class="kt">id</span> <span class="n">sectionValue</span> <span class="o">=</span> <span class="nb">nil</span><span class="p">;</span>
    <span class="kt">id</span> <span class="n">sectionRecords</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSMutableArray</span> <span class="n">array</span><span class="p">];</span>
    
    <span class="n">dispatch_block_t</span> <span class="n">split</span> <span class="o">=</span> <span class="o">^</span><span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span> <span class="p">[</span><span class="n">sectionRecords</span> <span class="n">count</span><span class="p">]</span> <span class="p">)</span> <span class="p">{</span>
            <span class="kt">id</span> <span class="n">lastRecord</span> <span class="o">=</span> <span class="p">[</span><span class="n">sectionRecords</span> <span class="nl">objectAtIndex:</span> <span class="mi">0</span><span class="p">];</span>
            <span class="kt">id</span> <span class="n">label</span> <span class="o">=</span> <span class="p">[</span><span class="n">lastRecord</span> <span class="nl">objectForKey:</span> <span class="n">labelKey</span><span class="p">];</span>
            <span class="kt">id</span> <span class="n">section</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSDictionary</span> <span class="nl">dictionaryWithObjectsAndKeys:</span>
                          <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithArray:</span> <span class="n">sectionRecords</span><span class="p">],</span> <span class="s">@"Records"</span><span class="p">,</span>
                          <span class="n">label</span><span class="p">,</span> <span class="s">@"Name"</span><span class="p">,</span>
                          <span class="nb">nil</span><span class="p">];</span>
            <span class="p">[</span><span class="n">sections</span> <span class="nl">addObject:</span> <span class="n">section</span><span class="p">];</span>
            <span class="p">[</span><span class="n">sectionRecords</span> <span class="n">removeAllObjects</span><span class="p">];</span>
        <span class="p">}</span>
    <span class="p">};</span>
    
    <span class="k">for</span> <span class="p">(</span><span class="kt">id</span> <span class="n">record</span> <span class="k">in</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">id</span> <span class="n">recordValue</span> <span class="o">=</span> <span class="p">[</span><span class="n">record</span> <span class="nl">objectForKey:</span> <span class="n">valueKey</span><span class="p">];</span>
        <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="p">[</span><span class="n">recordValue</span> <span class="nl">isEqual:</span> <span class="n">sectionValue</span><span class="p">]</span> <span class="p">)</span> <span class="p">{</span>
            <span class="n">split</span><span class="p">();</span>
            <span class="n">sectionValue</span> <span class="o">=</span> <span class="n">recordValue</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="p">[</span><span class="n">sectionRecords</span> <span class="nl">addObject:</span> <span class="n">record</span><span class="p">];</span>
    <span class="p">}</span>
    <span class="n">split</span><span class="p">();</span>
    
    <span class="k">return</span> <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithArray:</span> <span class="n">sections</span><span class="p">];</span>
<span class="p">}</span>
</pre></div>
</td>
</tr></table></div>
</div>

<p>Since the block by default has read-only access to any variable it wants as long as it&#8217;s in scope, there&#8217;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&#8217;s <a href="http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/Blocks">Block Programming Topics</a> for more about that. However, they&#8217;re a great tool for small problems as well that you shouldn&#8217;t overlook.</p>
]]></content:encoded>
			<wfw:commentRss>http://tewha.net/2011/07/blocks-to-remove-redundancy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>12 Myths About Concurrency in Objective-C</title>
		<link>http://tewha.net/2011/06/12-myths-about-concurrency-in-objective-c/</link>
		<comments>http://tewha.net/2011/06/12-myths-about-concurrency-in-objective-c/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 22:21:06 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1164</guid>
		<description><![CDATA[12 Myths About Concurrency in Objective-C]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.random-ideas.net/?p=28">12 Myths About Concurrency in Objective-C</a></p>
]]></content:encoded>
			<wfw:commentRss>http://tewha.net/2011/06/12-myths-about-concurrency-in-objective-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>foo() vs foo(void)</title>
		<link>http://tewha.net/2011/05/foo-vs-foovoid/</link>
		<comments>http://tewha.net/2011/05/foo-vs-foovoid/#comments</comments>
		<pubDate>Wed, 25 May 2011 22:57:04 +0000</pubDate>
		<dc:creator>Steven Fisher</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[objective-c]]></category>

		<guid isPermaLink="false">http://tewha.net/?p=1163</guid>
		<description><![CDATA[Old content, but I just needed it now: The difference between foo() and foo(void) by Greg Miller. Hint: Objective-C doesn&#8217;t follow the C++ pattern. You probably want foo(void).]]></description>
			<content:encoded><![CDATA[<p>Old content, but I just needed it now: <a href="http://unixjunkie.blogspot.com/2006/03/difference-between-foo-and-foovoid.html">The difference between <code>foo()</code> and <code>foo(void)</code></a> by Greg Miller.</p>

<p>Hint: Objective-C doesn&#8217;t follow the C++ pattern. You probably want <code>foo(void)</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tewha.net/2011/05/foo-vs-foovoid/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced

Served from: tewha.net @ 2012-02-04 02:33:35 -->
