<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>David Linsin</title>
 <link href="http://dlinsin.github.com/atom.xml" rel="self"/>
 <link href="http://dlinsin.github.com/"/>
 <updated>2012-05-01T08:01:18-07:00</updated>
 <id>http://dlinsin.github.com/</id>
 <author>
   <name>David Linsin</name>
   <email>dlinsin@gmail.com</email>
 </author>

 
 <entry>
   <title>Test-Driven iOS Development</title>
   <link href="http://dlinsin.github.com/2012/05/01/Test-Driven-iOS-Development.html"/>
   <updated>2012-05-01T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2012/05/01/Test-Driven-iOS-Development</id>
   <content type="html">&lt;p&gt;A couple of weeks ago, I started reading &lt;a href='http://www.amazon.de/gp/product/0321774183?ie=UTF8&amp;amp;tag=mytakeonthing-21&amp;amp;linkCode=as2&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;creativeASIN=0321774183'&gt;&lt;em&gt;Test-Driven iOS Development&lt;/em&gt;&lt;/a&gt; by &lt;a href='http://twitter.com/secboffin'&gt;Graham Lee&lt;/a&gt;. I had a blast reminiscing about my days as a Java developer, where every piece of code had a &lt;em&gt;unit test&lt;/em&gt; counterpart.&lt;/p&gt;

&lt;p&gt;Graham is doing a great job introducing the notion behind unit testing and answering the basic question of why you should write unit tests for your code. The book mentions unit tests can be documentation, help you think about API design and a way to get to know &lt;a href='http://dlinsin.blogspot.de/2007/07/hell-is-other-peoples-code.html'&gt;other people&amp;#8217;s code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I especially like the way Graham talks about &lt;em&gt;Refactoring&lt;/em&gt;. I&amp;#8217;ve read a couple of books on this kind of topic, the difference with &lt;a href='http://www.amazon.de/gp/product/0321774183?ie=UTF8&amp;amp;tag=mytakeonthing-21&amp;amp;linkCode=as2&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;creativeASIN=0321774183'&gt;&lt;em&gt;Test-Driven iOS Development&lt;/em&gt;&lt;/a&gt; is that I really enjoyed how &lt;em&gt;Refactoring&lt;/em&gt; is a steady topic through-out the whole book.&lt;/p&gt;

&lt;p&gt;For me one of the most important reasons for writing unit tests is not so much to show that something works &lt;em&gt;now&lt;/em&gt;, but to have that safety net some time in the &lt;em&gt;future&lt;/em&gt;, which helps you to make sure things still work after refactoring your code.&lt;/p&gt;

&lt;p&gt;Graham uses a sample App, which is available on &lt;a href='https://github.com/iamleeg/BrowseOverflow'&gt;Github&lt;/a&gt;, to show how to approach unit testing on basically every layer of an iOS App. It covers setting up OCUnit in Xcode, a couple of interesting testing frameworks and tools, all the way to testing the view layer with a &lt;em&gt;UITableView&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The most interesting aspects of the chapters about the sample App, was how to design your classes with testing in mind. I&amp;#8217;ve &lt;a href='http://dlinsin.blogspot.de/2008/06/nothing-wrong-with-tdd-right.html'&gt;never been&lt;/a&gt; a big proponent of a &lt;a href='http://en.wikipedia.org/wiki/Test-first'&gt;test-first&lt;/a&gt;, however, Graham shows with no doubt, that it has advantages. The most important one, in my opinion, is that it makes you &lt;em&gt;think&lt;/em&gt; about the API of your class, &lt;em&gt;before&lt;/em&gt; starting to code.&lt;/p&gt;

&lt;p&gt;Overall, &lt;a href='http://www.amazon.de/gp/product/0321774183?ie=UTF8&amp;amp;tag=mytakeonthing-21&amp;amp;linkCode=as2&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;creativeASIN=0321774183'&gt;&lt;em&gt;Test-Driven iOS Development&lt;/em&gt;&lt;/a&gt; is really worth reading, especially if you are new to test-driven development or need some revision on the topic. The book contains lots of code and even though I usually don&amp;#8217;t mind, I sometimes had a hard time staying on top of it.&lt;/p&gt;

&lt;p&gt;If you are not practicing test-driven development today, I highly recommend reading &lt;a href='http://www.amazon.de/gp/product/0321774183?ie=UTF8&amp;amp;tag=mytakeonthing-21&amp;amp;linkCode=as2&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;creativeASIN=0321774183'&gt;&lt;em&gt;Test-Driven iOS Development&lt;/em&gt;&lt;/a&gt; and let Graham show you its benefits.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Mantis to Issues Safari Extension</title>
   <link href="http://dlinsin.github.com/2012/04/01/Mantis-to-Issues-Safari-Extension.html"/>
   <updated>2012-04-01T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2012/04/01/Mantis-to-Issues-Safari-Extension</id>
   <content type="html">&lt;p&gt;Back in January I wrote a &lt;a href='https://extensions.apple.com/'&gt;Safari Extension&lt;/a&gt; called &lt;a href='https://github.com/dlinsin/Mantis-Issues-Ext'&gt;Mantis-Issues-Ext&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It extracts information from an issue of a Mantis bugtracking system and adds it to a GitHub issue&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It&amp;#8217;s available on &lt;a href='https://github.com/dlinsin/Mantis-Issues-Ext/downloads'&gt;GitHub&lt;/a&gt;, where you can download it or directly install it into Safari.&lt;/p&gt;

&lt;p&gt;At my day job our whole development workflow is based on GitHub. We document our requirements, push our code and keep our issues in GitHub. Unfortunately, our customers are using different systems. Among others, the horrible &lt;a href='http://www.mantisbt.org/'&gt;Mantis Bug Tracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of going the route of forcing our customers to use our system, we are usually going the extra mile of maintaining two systems - e.g. Mantis and GitHub (at least for issues). In order to make life easier for our developers, I came up with Mantis-Issues-Ext.&lt;/p&gt;

&lt;p&gt;Here is how it works: you can navigate to an issue in Mantis, hit a shortcut, create a new issue in GitHub and with another shortcut fill in all the relevant information.&lt;/p&gt;

&lt;p&gt;Although it doesn&amp;#8217;t help with the maintenance part, it makes life easier when creating issues.&lt;/p&gt;

&lt;p&gt;Now let me say that I&amp;#8217;m not a JavaScript guru and Safari Extensions are mainly based on JavaScript. I don&amp;#8217;t really enjoy developing with web technologies - I&amp;#8217;m a downright native guy. That said, I think my code probably sucks and could definitely be improved. However, it works and that&amp;#8217;s the main goal of this extension.&lt;/p&gt;

&lt;p&gt;Apple makes a great job - as always - in &lt;a href='http://developer.apple.com/library/safari/#documentation/Tools/Conceptual/SafariExtensionGuide/Introduction/Introduction.html'&gt;documenting Safari Extentions&lt;/a&gt;. However, the development experience in Safari is not as great as I would have imagined. You need to add a lot of logging in order to really see what&amp;#8217;s going on, but I guess if JavaScript is your thing, it should be quite easy for your to get something going.&lt;/p&gt;

&lt;p&gt;Unfortunately, I wasn&amp;#8217;t able to setup an automatic update mechanism for &lt;a href='https://github.com/dlinsin/Mantis-Issues-Ext'&gt;Mantis-Issues-Ext&lt;/a&gt; yet. You need to fiddle with the MIME types of your web server and I just don&amp;#8217;t have anything in place for that.&lt;/p&gt;

&lt;p&gt;I hope Mantis-Issues-Ext makes life easier for some folks out there and helps you focus on working in GitHub instead of Mantis.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Focus</title>
   <link href="http://dlinsin.github.com/2012/02/12/Focus.html"/>
   <updated>2012-02-12T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2012/02/12/Focus</id>
   <content type="html">&lt;p&gt;The latest update of &lt;a href='http://ffapps.me/bahn'&gt;&amp;#8220;Cologne Train&amp;#8221;&lt;/a&gt; (aka &amp;#8220;Bahn Köln&amp;#8221;), which hit the App Store a &lt;a href='http://twitter.com/#!/furryfishApps/status/168091577032511488'&gt;couple of days ago&lt;/a&gt;, reflects &lt;a href='http://furryfishApps.com'&gt;furryfishApps&lt;/a&gt; continuos effort of narrowing the focus while at the same time increasing the value for the user.&lt;/p&gt;

&lt;p&gt;We believe that the focus of our App, even though it was already very narrow, was still too wide and needed some redefinition. This is by the way quite opposed to what people tell us in their &lt;a href='http://dlinsin.github.com/2011/11/20/AppStoreRatings.html'&gt;App Store ratings&lt;/a&gt;. They always want more bells &amp;amp; whistles and they all want it for free. So our decision to narrow the focus of &amp;#8220;Cologne Train&amp;#8221; might seem contradicting. However, we believe it&amp;#8217;s the right step:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The more narrow focused an App is, the better it can be at what it does - hence more valuable for the user.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As outlined in a &lt;a href='http://dlinsin.github.com/2011/07/31/Appdate.html'&gt;previous blog post&lt;/a&gt;: the original purpose of the App, which was notifications about train disruptions, has already been demoted to a second class feature. With the latest update, it disappears into the background and is merely an add-on. Don&amp;#8217;t get me wrong, it&amp;#8217;s still there and works as advertised, however the main focus of the App has shifted to displaying the most up to date train arrival times in Cologne.&lt;/p&gt;

&lt;p&gt;This change has come a long way. We have been thinking about this move since September and running a prototype with various versions for a couple of months. We wanted to get it right and integrate the former main feature as seamlessly as possible with our vision of a more narrow focus.&lt;/p&gt;

&lt;p&gt;So far the feedback has mostly been positiv and we are quite happy to have once more narrowed the focus and at the same time increased the value of &lt;a href='http://ffapps.me/bahn'&gt;&amp;#8220;Cologne Train&amp;#8221;&lt;/a&gt; (aka &amp;#8220;Bahn Köln&amp;#8221;).&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Crash Reporting - Don't let your user do quality assurance</title>
   <link href="http://dlinsin.github.com/2012/01/07/crashreporting.html"/>
   <updated>2012-01-07T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2012/01/07/crashreporting</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m not a big fan of crash reporting in App Store Apps. In a lot of discussions with developers I had the feeling they see it as some kind of quality assurance. As if it would replace thorough testing, because you can fix everything with an update. I think it&amp;#8217;s not a user&amp;#8217;s job to find bugs and report them to you. It&amp;#8217;s your job as a developer to go the extra mile and test your App to ensure a sufficient level of quality.&lt;/p&gt;

&lt;p&gt;That said, I do realize it&amp;#8217;s almost impossible to find every bug and to test every possible scenario. That&amp;#8217;s why I decided to add crash reporting to furryfishApps&amp;#8217; latest App &lt;a href='http://ffapps.me/bahn'&gt;&amp;#8220;Bahn Köln&amp;#8221;&lt;/a&gt;, when being asked by &lt;a href='http://crashlytics.com/'&gt;Crashlytics&lt;/a&gt; to join their private beta program.&lt;/p&gt;

&lt;p&gt;When reading about Crashlytics I expected it to be one of those frameworks, which is almost impossible to integrate with an existing App. To my surprise it was quite the contrary. Everything was setup within a couple minutes, it couldn&amp;#8217;t have been more hassle-free. It&amp;#8217;s worth checking out if you consider adding crash reporting to your App.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s been two weeks since the first version with crash reporting shipped. Almost 1600 users (about 60%) installed the update and with the Christmas holidays and new years eve, we&amp;#8217;ve got some pretty good usage numbers to draw a conclusion.&lt;/p&gt;

&lt;p&gt;Overall we had about 4 crash related issues, with merely 15 users affected. That&amp;#8217;s 1% of the users who installed the update. Keep in mind: we decided to not send reports automatically. The user must agree to send them, hence there&amp;#8217;s a good chance we missed a couple of reports. However, due to the &lt;a href='http://dlinsin.github.com/2011/07/31/Appdate.html'&gt;thought&lt;/a&gt; we put into each and every decision of our App, we can be quite happy with the numbers.&lt;/p&gt;

&lt;p&gt;From a developer&amp;#8217;s perspective the numbers are secondary. What&amp;#8217;s important is the source of the crashes. As it turned out, only 1 crash was actually a programming error. I forgot to check the length of an array - a stupid mistake, which surfaced in an edge-case. All other crashes were weird side-effects from our very unstable datasource - the &lt;a href='http://www.kvb-koeln.de/generator/index.html'&gt;KVB-Widget generator&lt;/a&gt;. We try our best to protect the user from those side-effects, unfortunately it doesn&amp;#8217;t always work.&lt;/p&gt;

&lt;p&gt;My reservations when it comes to crash reporting remain: It doesn&amp;#8217;t replace thorough testing - on various devices and in different scenarios. Don&amp;#8217;t let your user do quality assurance.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>In My Humble Opinion</title>
   <link href="http://dlinsin.github.com/2011/12/30/in-my-humble-opinion.html"/>
   <updated>2011-12-30T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/12/30/in-my-humble-opinion</id>
   <content type="html">&lt;p&gt;&lt;em&gt;In my humble opinion&lt;/em&gt; aka &lt;em&gt;IMHO&lt;/em&gt; is a phrase you hear quite often in technical discussions found on blogs or &lt;a href='http://twitter.com/dlinsin'&gt;twitter&lt;/a&gt;. It&amp;#8217;s nothing new and doesn&amp;#8217;t need further explanation, since you&amp;#8217;ve used it probably a thousand times, just like me. However, I&amp;#8217;d like to talk about the small, but quite important difference between &lt;strong&gt;opinion&lt;/strong&gt; and &lt;strong&gt;fact&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I think (notice, how I didn&amp;#8217;t use &lt;em&gt;IMHO&lt;/em&gt; here) that in most cases, especially when using &lt;em&gt;IMHO&lt;/em&gt; in a face to face discussion, the word &lt;strong&gt;opinion&lt;/strong&gt; actually could be replaced with &lt;strong&gt;fact&lt;/strong&gt;, &lt;strong&gt;truth&lt;/strong&gt; or &lt;strong&gt;verity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I have noticed this for a while and came to the conclusion that the iOS developer community is worse in this regard than the Java community. I&amp;#8217;m not too sure why. I assume it&amp;#8217;s due to the fact that most of the iOS developers are working on their own, whereas the typical Java developer usually works in a team. I guess you tend to confuse &lt;strong&gt;opinion&lt;/strong&gt; with &lt;strong&gt;fact&lt;/strong&gt; much easier, if you are the only one involved in a project. Every decision you make caters to your own needs and is mostly a perfect fit.&lt;/p&gt;

&lt;p&gt;A couple of years ago I read a blog post from &lt;a href='http://en.wikipedia.org/wiki/Jeff_Atwood'&gt;Jeff Atwood&lt;/a&gt; on &lt;a href='http://www.codinghorror.com/blog/2008/05/strong-opinions-weakly-held.html'&gt;Coding Horror&lt;/a&gt;, which has been my mantra in terms of voicing my opinion ever since:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I suppose it&amp;#8217;s also an issue of personal style. To me, writing without a strong voice, writing filled with second guessing and disclaimers, is tedious and difficult to slog through. I go out of my way to write in a strong voice because it&amp;#8217;s more effective. But whenever I post in a strong voice, it is also an implied invitation to a discussion, a discussion where I often change my opinion and invariably learn a great deal about the topic at hand. I believe in the principle of strong opinions, weakly held&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have been applying the principle of &lt;strong&gt;strong opinions, weakly held&lt;/strong&gt; in almost every discussion I had or blog post I published.&lt;/p&gt;

&lt;p&gt;My opinions are usually deduced from personal experience and observation, so I will try to defend them to a certain degree. However, I&amp;#8217;m more than happy to reconsider my position, if there&amp;#8217;s a valid argument against it.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>App Store Ratings</title>
   <link href="http://dlinsin.github.com/2011/11/20/AppStoreRatings.html"/>
   <updated>2011-11-20T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/11/20/AppStoreRatings</id>
   <content type="html">&lt;p&gt;Inspired by a &lt;a href='http://twitter.com/#!/coderWarning/status/137563714571354113'&gt;couple&lt;/a&gt; of &lt;a href='http://twitter.com/#!/mattcomi/status/137913269817057280'&gt;tweets&lt;/a&gt; from fellow iOS developer &lt;a href='http://thecodingerror.github.com/'&gt;Max&lt;/a&gt; and my own experiences with bad App Store ratings over the past two and a half years, I&amp;#8217;ll give you my 2 cents in this blog post.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t want to point out any solutions or suggest what Apple could change. I&amp;#8217;d rather like to&lt;br /&gt;highlight what I think motivates the average Joe user to give you a 1-star rating. Maybe it&amp;#8217;ll help you understand why your App gets bad ratings and hurtful reviews.&lt;/p&gt;

&lt;p&gt;First motivation for a bad rating that comes into mind: your App sucks! It is very easy for average Joe to say that your App sucks. Especially, if he had to pay for it. If your App says it plays music in the background, it must play music in the background! It doesn&amp;#8217;t matter to average Joe, that it is not supported on iOS 3 - your App just sucks to him! Average Joe does not read the big disclaimer in your App description and the UIAlertView telling him, that background process are not supported on his version of iOS was dismissed without any notice.&lt;/p&gt;

&lt;p&gt;Second reason that I can think of: you are screwing him! The average Joe likes his Apps to be free! That&amp;#8217;s one reason why average Joe&amp;#8217;s platform of choice is Android - everything is free! Now, you and I know the world doesn&amp;#8217;t come in &amp;#8220;free&amp;#8221;. Chances are high, that you have to operate some sort of backend or pay a designer - maybe both. Well, guess what? Average Joe doesn&amp;#8217;t know and doesn&amp;#8217;t care. He wants his App for free - although, he is willing to make you a huge courtesy by paying 0.99 cents at most. For average Joe this means: lifetime support and a service with 99.99999% uptime - no big deal!&lt;/p&gt;

&lt;p&gt;Third motivation which definitely gets you a 1-star rating: your App doesn&amp;#8217;t get him laid! Even you and I know, that we are sometimes guilty of &amp;#8220;RTFM&amp;#8221;, but as I mentioned before, it applies to average Joe ALL THE TIME! Average Joe doesn&amp;#8217;t care if your App is not meant to get him laid, if he thinks it&amp;#8217;s supposed to, he&amp;#8217;ll tell you! The bad news for you and me is, that he doesn&amp;#8217;t know how E-Mail works, but hey - he knows his way around the App Store ratings system! It&amp;#8217;s easy enough to hit that 1 star and write &amp;#8220;Doesn&amp;#8217;t do X, Y and Z!&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Now, I assume, since you are still reading this, you care about your App and I&amp;#8217;m pretty sure it doesn&amp;#8217;t suck or at least you are trying. Well, I developed a lot of Apps and frankly some of them might not be masterpieces. However, if I get an App for free, I&amp;#8217;ll never go out and give a 1-star rating, because I know how much work went into such an App. That&amp;#8217;s exactly the difference between me and average Joe - they don&amp;#8217;t know and they don&amp;#8217;t care.&lt;/p&gt;

&lt;p&gt;For &lt;a href='http://furryfishapps.com'&gt;furryfishApps&amp;#8217;&lt;/a&gt; latest App &lt;a href='http://ffapps.me/bahn'&gt;&amp;#8220;Cologne Train&amp;#8221;&lt;/a&gt;, we put a lot of thoughts into optimizing the App&amp;#8217;s workflow and usability, just to get &lt;a href='http://twitter.com/#!/dlinsin/status/132425112384323584'&gt;bad reviews&lt;/a&gt; falling into the three mentioned categories. I really don&amp;#8217;t mind getting bad reviews for a crashing App or one that doesn&amp;#8217;t work as advertised, but I think we always will - thanks to average Joe!&lt;/p&gt;

&lt;p&gt;I guess the recipe for 5-star App Store reviews might be: don&amp;#8217;t screw average Joe, so he has enough money to get laid and show off, with an App that doesn&amp;#8217;t suck!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>AppDev Meet November</title>
   <link href="http://dlinsin.github.com/2011/11/15/AppDevMeetNov.html"/>
   <updated>2011-11-15T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/11/15/AppDevMeetNov</id>
   <content type="html">&lt;p&gt;Last months edition of &lt;a href='http://git.io/FOzYiA'&gt;AppDev Meet&lt;/a&gt; was &lt;a href='http://twitter.com/#!/appdevmeet/status/126745611478384640'&gt;awesome&lt;/a&gt;, so we are looking forward to a new installment this months:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We will meet on Thursday, Nov 17th - 18:00 at &lt;a href='http://goo.gl/CrhYU'&gt;Starbucks near Neumarkt in Cologne&lt;/a&gt; (&lt;a href='http://www.doodle.com/export/ics?optionIndex=7&amp;amp;locale=en&amp;amp;timeZone=Europe%2FBerlin&amp;amp;adminKey=&amp;amp;pollId=a5sn427cr94n6iwg&amp;amp;participantKey='&gt;Calendar Export&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to stay updated and informed you should follow AppDev Meet on Twitter &lt;a href='http://twitter.com/appdevmeet'&gt;@appdevmeet&lt;/a&gt;!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Git.io OS X Service</title>
   <link href="http://dlinsin.github.com/2011/11/13/Git-io-OS-X-Service.html"/>
   <updated>2011-11-13T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/11/13/Git-io-OS-X-Service</id>
   <content type="html">&lt;p&gt;I&amp;#8217;m a &lt;a href='http://twitter.com/#!/dlinsin/status/110584408817405953'&gt;big fan&lt;/a&gt; of &lt;a href='http://github.com'&gt;GitHub&lt;/a&gt; as some of you might know, so it was a pleasant surprise when they released their very own URL shortener - &lt;a href='https://github.com/blog/985-git-io-github-url-shortener'&gt;Git.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Services like that always &lt;a href='https://github.com/dlinsin/github-java-api'&gt;inspire me&lt;/a&gt; to build stuff on top of them. It&amp;#8217;s just great to see companies you love come up with cool stuff to play with. Sutini and I even had a brainstorming session over a nice cup of Starbucks coffee, whether this could be a project for &lt;a href='http://furryfishApps.com'&gt;furryfishApps&lt;/a&gt;. I wanted a simple way to generate Git.io URLs for pasting into E-Mails or Tweets. I could think of more features, but that&amp;#8217;s the basic requirement.&lt;/p&gt;

&lt;p&gt;Eventually, I decided to come up with a simple Mac OS X Service. When installed, you can highlight any GitHub URL, navigate to OS X&amp;#8217;s Services Menu and generate a Git.io URL. You&amp;#8217;ll get a nice &lt;a href='http://growl.info/'&gt;Growl&lt;/a&gt; notification displaying the original URL and the shortened version. In addition to that you can instantly paste the Git.io URL into your E-Mail or Tweet.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s a lot to improve and it doesn&amp;#8217;t work under certain conditions, however you can grab an unpolished version of the Service from my &lt;a href='https://github.com/dlinsin/Git.io-OS-X-Service'&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>AppDev Meet October</title>
   <link href="http://dlinsin.github.com/2011/10/09/AppDevMeetOctober.html"/>
   <updated>2011-10-09T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/10/09/AppDevMeetOctober</id>
   <content type="html">&lt;p&gt;As mentioned &lt;a href='http://dlinsin.github.com/2011/09/28/AppDevMeetOctober.html'&gt;last week&lt;/a&gt;, the dates for AppDev Meet October were up for voting on &lt;a href='http://doodle.com/2scu8yvs2353wmru'&gt;Doodle&lt;/a&gt;. Although, there was a choice between 2 suitable dates, there can only be one winner:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App Dev Meet October will be on Wednesday, October 19th 18:00 at &lt;a href='http://goo.gl/CrhYU'&gt;Starbucks near Neumarkt in Cologne&lt;/a&gt; (&lt;a href='http://doodle.com/export/ics?optionIndex=6&amp;amp;locale=en&amp;amp;timeZone=Europe%2FBerlin&amp;amp;adminKey=&amp;amp;pollId=2scu8yvs2353wmru&amp;amp;participantKey='&gt;Calendar Export&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Last time there was plenty of space, however please remember: Starbucks is a public venue, seats are available on first come first serve basis.&lt;/p&gt;

&lt;p&gt;Please follow AppDev Meet on Twitter &lt;a href='http://twitter.com/appdevmeet'&gt;@appdevmeet&lt;/a&gt; for updates and further information!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>AppDev Meet October</title>
   <link href="http://dlinsin.github.com/2011/09/28/AppDevMeetOctober.html"/>
   <updated>2011-09-28T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/09/28/AppDevMeetOctober</id>
   <content type="html">&lt;p&gt;Our &lt;a href='http://dlinsin.github.com/2011/09/04/FirstAppDevMeet.html'&gt;first AppDev Meet&lt;/a&gt; took place a couple of weeks ago with &lt;a href='http://twitter.com/sutinisaid'&gt;@sutinisaid&lt;/a&gt;, &lt;a href='http://twitter.com/coderWarning'&gt;@coderWarning&lt;/a&gt;, &lt;a href='http://twitter.com/daniel_a_a'&gt;@daniel_a_a&lt;/a&gt; and &lt;a href='http://twitter.com/anGrauel'&gt;@anGrauel&lt;/a&gt;. We talked about @coderWarning&amp;#8217;s plans for his iOS App &lt;a href='http://itunes.apple.com/app/risikoanalyse/id446628827?mt=8'&gt;&amp;#8220;Risikoanalyse&amp;#8221;&lt;/a&gt; as well as development for the Mac with @daniel_a_a and his App &lt;a href='http://itunes.apple.com/de/app/timing-time-tracking-for-humans/id431511738?mt=12'&gt;&amp;#8220;Timing&amp;#8221;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our October installment will take place here in Cologne again, following the same &lt;a href='https://gist.github.com/1170946'&gt;formular&lt;/a&gt;. In order to find a date, we&amp;#8217;d like to ask you to head over to &lt;a href='http://doodle.com/2scu8yvs2353wmru'&gt;doodle&lt;/a&gt; and fill in your dates of choice.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ll announce the winning date on twitter, so if you haven&amp;#8217;t already, you should follow AppDev Meet on Twitter &lt;a href='http://twitter.com/appdevmeet'&gt;@appdevmeet&lt;/a&gt; to stay up to date!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>AppCode Screencast</title>
   <link href="http://dlinsin.github.com/2011/09/19/AppCode-Screencast.html"/>
   <updated>2011-09-19T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/09/19/AppCode-Screencast</id>
   <content type="html">&lt;p&gt;A couple of weeks ago I &lt;a href='http://dlinsin.github.com/2011/08/27/AppCode.html'&gt;blogged&lt;/a&gt; about &lt;a href='http://www.jetbrains.com/objc/' title='AppCode'&gt;AppCode&lt;/a&gt; and my reasons to stick with it, even though it wasn&amp;#8217;t production ready yet. Since then Jetbrains announce that &lt;a href='http://feedproxy.google.com/~r/jetbrains_appcode/~3/HYzRH80bAvI/'&gt;AppCode 1.0 is imminent&lt;/a&gt; and released a beta version.&lt;/p&gt;

&lt;p&gt;They also give you the &lt;a href='http://blog.jetbrains.com/objc/2011/09/show-why-you-love-appcode-and-get-it-free-oh-and-win-an-ipad/'&gt;chance to get a free version&lt;/a&gt;, by show off what you like about AppCode in a screencast. Since I&amp;#8217;m already in love with AppCode, I took my chances and produced a &lt;a href='http://tv.jetbrains.net/videocontent/productivity-with-appcode'&gt;video&lt;/a&gt; of my favorite features. Unfortunately, I only noticed the horrible quality only after I already edited and tweaked the whole thing. I do apologize and hope you like it anyways.&lt;/p&gt;
&lt;object data='http://tv.jetbrains.net/flowplayer/flowplayer-3.2.7.swf' id='_ipad' type='application/x-shockwave-flash' height='450' width='500'&gt;&lt;param name='movie' value='http://tv.jetbrains.net/flowplayer/flowplayer-3.2.7.swf' /&gt;&lt;param name='allowfullscreen' value='true' /&gt;&lt;param name='allowscriptaccess' value='always' /&gt;&lt;param name='flashvars' value='config={&quot;clip&quot;:{&quot;scaling&quot;:&quot;orig&quot;,&quot;autoPlay&quot;:false,&quot;autoBuffering&quot;:true,&quot;url&quot;:&quot;/sites/default/files/videos/converted/AppCode_Screencast.mp4&quot;},&quot;plugins&quot;:{&quot;controls&quot;:{&quot;stop&quot;:true}},&quot;playlist&quot;:[{&quot;scaling&quot;:&quot;orig&quot;,&quot;autoPlay&quot;:false,&quot;autoBuffering&quot;:true,&quot;url&quot;:&quot;http://tv.jetbrains.net/sites/default/files/videos/converted/AppCode_Screencast.mp4&quot;}]}' /&gt;&lt;/object&gt;
&lt;p&gt;None flash version &lt;a href='http://tv.jetbrains.net/sites/default/files/videos/converted/AppCode_Screencast.mp4'&gt;here&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>First AppDev Meet</title>
   <link href="http://dlinsin.github.com/2011/09/04/FirstAppDevMeet.html"/>
   <updated>2011-09-04T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/09/04/FirstAppDevMeet</id>
   <content type="html">&lt;p&gt;A couple of weeks ago, &lt;a href='http://dlinsin.github.com/2011/08/25/AppDevMeet.html'&gt;I blogged about&lt;/a&gt; our plans for the &lt;a href='https://gist.github.com/1170946'&gt;first AppDev Meet&lt;/a&gt; here in Cologne. The feedback was amazing and we had a good number of people participating in our &lt;a href='http://doodle.com/erxb67rqzr57298k'&gt;poll&lt;/a&gt; to find a date. Luckily we had a clear winner:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first App Dev Meet will be on Tuesday, September 13th 18:00 at &lt;a href='http://goo.gl/CrhYU'&gt;Starbucks near Neumarkt in Cologne&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We think there should be enough space for everyone who participated in the doodle. However please remember: Starbucks is a public venue, seats are available on first come first serve basis.&lt;/p&gt;

&lt;p&gt;If you haven&amp;#8217;t already, you should follow App Dev Meet on Twitter &lt;a href='http://twitter.com/appdevmeet'&gt;@appdevmeet&lt;/a&gt; to stay up to date!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>AppCode</title>
   <link href="http://dlinsin.github.com/2011/08/27/AppCode.html"/>
   <updated>2011-08-27T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/08/27/AppCode</id>
   <content type="html">&lt;p&gt;I recently announced on &lt;a href='http://twitter.com/#!/furryfishApps/status/103699334406742016'&gt;twitter&lt;/a&gt;, that I&amp;#8217;d be using &lt;a href='http://www.jetbrains.com/objc/' title='AppCode'&gt;AppCode&lt;/a&gt;, the Objective-C IDE from Jetbrains, in production for at least one week. It&amp;#8217;s almost two weeks now, here&amp;#8217;s what I experienced.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll get to the point quickly here: It&amp;#8217;s a pleasure to develop with AppCode! If you are looking for a strong editor with solid refactoring support, go get AppCode&amp;#8217;s 1.0 and never use Xcode&amp;#8217;s editor again. If you&amp;#8217;ve used any other Jetbrains product, you&amp;#8217;ll feel at home instantly. Version Control works out of the box and the debugging UI is a lot more stable than in Xcode.&lt;/p&gt;

&lt;p&gt;If I haven&amp;#8217;t convinced you yet, keep on reading.&lt;/p&gt;

&lt;p&gt;AppCode has great refactoring support. Out of the box, the most important refactorings are assigned to keyboard shortcuts, you are accustomed to if you&amp;#8217;ve used e.g. &lt;a href='http://www.jetbrains.com/idea'&gt;IntelliJ&lt;/a&gt;. However, the biggest advantage over Xcode is the variety of refactorings: &amp;#8220;Introduce Variable&amp;#8221; or &amp;#8220;Extract Block&amp;#8221; is something that Xcode doesn&amp;#8217;t offer you and I would already miss it.&lt;/p&gt;

&lt;p&gt;The stability of the EAP build is great, it&amp;#8217;s still buggy, but let&amp;#8217;s face it: you&amp;#8217;ve probably seen Xcode&amp;#8217;s &amp;#8220;Crash or Continue&amp;#8221; dialog &lt;a href='http://twitter.com/bmf/status/106144603647909889'&gt;at least&lt;/a&gt; &lt;a href='http://twitter.com/chockenberry/status/106068158145765376'&gt;once&lt;/a&gt; the past couple days - with a &amp;#8220;stable&amp;#8221; version. No matter what went wrong the past week AppCode never crashed! You get a notification, indicating something went wrong and a textfield to report a bug, which can be submitted directly from the App. However, everything kept working - no restart required.&lt;/p&gt;

&lt;p&gt;Although AppCode is great, there are some problems, which I mostly blame on the fact it&amp;#8217;s still EAP.&lt;/p&gt;

&lt;p&gt;I wasn&amp;#8217;t able to debug my iOS Apps on any device, which basically is a no-go for production usage. However, the iOS Simulator works fine, so I used Xcode for device debugging and AppCode for development. In a stable version this must be fixed, though.&lt;/p&gt;

&lt;p&gt;I only needed Xcode for Interface Builder, to edit Core Data Models or archiving/submitting to the App Store. Those things are not possible in AppCode and frankly, I don&amp;#8217;t think they&amp;#8217;ll ever be. I could imagine, that editing Core Data Models might be included, however for the other two tasks you&amp;#8217;ll need to fall back to Xcode. Personally, I don&amp;#8217;t mind switching between applications, however, I can see that this might not appeal to everyone.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll continue using AppCode, even in production, since for me a strong editor is much more worth than an integrated experience. However, I&amp;#8217;m looking forward for AppCode&amp;#8217;s first stable version.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>AppDev Meet</title>
   <link href="http://dlinsin.github.com/2011/08/25/AppDevMeet.html"/>
   <updated>2011-08-25T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/08/25/AppDevMeet</id>
   <content type="html">&lt;p&gt;&lt;a href='http://twitter.com/sutinisaid'&gt;Sutini&lt;/a&gt; had this great idea for a meet up similar to &lt;a href='http://nscodernight.com'&gt;NSCoderNight&lt;/a&gt;, but with a design angle. Welcome &lt;a href='https://gist.github.com/1170946'&gt;AppDev Meet&lt;/a&gt;! Here&amp;#8217;s our pitch:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What? &amp;#8220;AppDev Meet&amp;#8221;? Shouldn&amp;#8217;t it be called &amp;#8220;NSCoderNight&amp;#8221; or something?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes and no! We wanted to start something fresh and new, so we decided to update the name.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Okay!?! So is it still about code and stuff?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sure! AppDev Meet is about iOS and Mac development as well as UI/UX-Design. We want to hang out, code and meet fellow developers and designers from the Cologne area.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Will there be a presentation?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nope! No slides, no talk and no presentation. Just bring yourself, your code or design and some stuff to talk about. That doesn&amp;#8217;t mean there won&amp;#8217;t be presentations or talks in the future. However, it&amp;#8217;s not in scope for version 1.0.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sounds cool, where can I sign up?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Actually, you don&amp;#8217;t have to sign up! No, seriously! AppDev Meet is based on the idea to meet up once or twice a month on a weekday after work - you just show up or you don&amp;#8217;t. No strings attached - no hard feelings in case you cannot make it.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ll meet up at &lt;a href='http://goo.gl/CrhYU'&gt;Starbucks at Neumarkt in Cologne&lt;/a&gt; &lt;span&gt;1&lt;/span&gt;. It&amp;#8217;s easy to find and easy to reach.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So when&amp;#8217;s the next AppDev Meet?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You decide! We set up a &lt;a href='http://doodle.com/erxb67rqzr57298k'&gt;doodle&lt;/a&gt; to schedule possible dates for a kick-off. The dates with the most votes wins - easy.&lt;/p&gt;

&lt;p&gt;Please help us spread the word to fellow iOS/Mac developers as well as UI/UX-Designers. You can follow on Twitter &lt;a href='http://twitter.com/appdevmeet'&gt;@appdevmeet&lt;/a&gt; for the latest updates!&lt;/p&gt;

&lt;p&gt;&lt;span&gt;1&lt;/span&gt; in case there&amp;#8217;s no space at Starbucks for the estimated crowd, we can relocate to another location in Cologne, so keep an eye on &lt;a href='http://twitter.com/appdevmeet'&gt;@appdevmeet&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Appdate</title>
   <link href="http://dlinsin.github.com/2011/07/31/Appdate.html"/>
   <updated>2011-07-31T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/07/31/Appdate</id>
   <content type="html">&lt;p&gt;Our very own app dev shop &lt;a href='http://furryfishapps.com'&gt;furryfishApps&lt;/a&gt; has been busy lately. We&amp;#8217;ve been working hard on an App called &lt;a href='http://itunes.apple.com/app/bahn-koln/id437791701?mt=8' title='Köln Bahn'&gt;&amp;#8220;Cologne Train&amp;#8221;&lt;/a&gt;. As the name indicates, it makes life easier commuting via local trains here in Cologne.&lt;/p&gt;

&lt;p&gt;In this blog post I&amp;#8217;ll tell you a little bit about the app and highlight a couple of things, which I think are quite interesting. It&amp;#8217;s probably not going to get too technical and more informative.&lt;/p&gt;

&lt;p&gt;Cologne Train really serves our own needs. We commute almost daily and always ran into the problem of arriving at the train station just to notice that the train is either delayed due to some disruption or just left a couple of minutes ago. We wanted to know about disruptions and train departures before we leave the house - that&amp;#8217;s when the Cologne Train App idea was born. It took about 19 days from inception to 1.0, although I have only worked on the App a couple of hours everyday.&lt;/p&gt;

&lt;p&gt;For our first feature - informing users about disruptions - we built a custom server backend. It takes care of detecting disruptions and sending out Push Notifications. In our App, users can select which train lines they are interested in and &amp;#8220;subscribe&amp;#8221; to Push Notifications. It was one of our design goals to make our App as non-invasive as possible. If you are only commuting on train line 16, for example, you probably don&amp;#8217;t want to receive Push Notifications for any other lines and thanks to our custom server backend, you won&amp;#8217;t receive any.&lt;/p&gt;

&lt;p&gt;For Push Notifications we use &lt;a href='http://urbanairship.com' title='Urban Airship'&gt;Urban Airship&lt;/a&gt;, which is awesome! In case you&amp;#8217;ve never heard of them: Urban Airship provides an infrastructure for Apple Push Notifications (APN) as well as In-App Purchases. In plain English: they solve all those nitty-gritty details with Device Tokens and APN. They also provide an easy to use &lt;a href='https://github.com/dlinsin/ios-library' title='My fork'&gt;client library&lt;/a&gt;, which handles device registration and badge updates with Urban Airship. It also helps to configure &amp;#8220;quiet times&amp;#8221;, another feature, which helps our App with non-invasiveness.&lt;/p&gt;

&lt;p&gt;Although it&amp;#8217;s great to know about train disruptions, something was missing. We also wanted our App to know when the next train would leave at our station. However, our App is not meant as a timetable App, it&amp;#8217;s merely meant to save you a couple of minutes, when leaving the house. It&amp;#8217;ll show you an estimate of how many minutes you&amp;#8217;ve got until the train arrives at the station of your choice. It updates live, meaning if the train takes longer that estimated, it&amp;#8217;ll adjust appropriately.&lt;/p&gt;

&lt;p&gt;In order to implement this, we tap into the local train companies website, which fortunately, offers a little html snippet, which you can add to your own website. It&amp;#8217;s easy and fast enough to parse on the device and scales nicely up to a couple of dozen stations.&lt;/p&gt;

&lt;p&gt;Due to the fact that Cologne doesn&amp;#8217;t have too many stations, we decided to offer a preloaded indexed list, as opposed to an &amp;#8220;only searching&amp;#8221; feature. It was a design decision, which we believe, makes the App feel rather concise and easy to use. There&amp;#8217;s still a search bar, however the fact that users can instantly scroll through the list, makes the App feel even more native.&lt;/p&gt;

&lt;p&gt;Unfortunately, there are situations when our App cannot display any information, e.g. due to a downtime of the local train companies systems or a disruption of network service. However, if the user just refreshed the content a couple of minutes ago, we think the information displayed is still valid. So we decided to not discard the displayed disruptions or train times, but rather add a subtle notification to indicate something went wrong. There are a lot of Apps replacing the content with an error message, which we believe is simply a bad design decision.&lt;/p&gt;

&lt;p&gt;Although our App looks quite simple, we pondered over little design decisions like the latter a lot! We want our App to be as helpful and non-invasiv as possible, mostly because we also use it every day.&lt;/p&gt;

&lt;p&gt;A couple of days ago version 2.1 was approved, which mainly fixes some bugs. However, we have a lot more ideas to come, so stay tuned. Oh and &lt;a href='http://twitter.com/furryfishApps'&gt;we love feedback&lt;/a&gt;!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Dismiss Keyboard on Tap "Outside"</title>
   <link href="http://dlinsin.github.com/2011/06/04/DismissKeyboardOnTapOutside.html"/>
   <updated>2011-06-04T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/06/04/DismissKeyboardOnTapOutside</id>
   <content type="html">&lt;p&gt;In almost every App I&amp;#8217;ve developed so far, the client requested to be able to dismiss the keyboard by tapping &amp;#8220;outside&amp;#8221; of an input area like an &lt;em&gt;UITextField&lt;/em&gt; or &lt;em&gt;UITextArea&lt;/em&gt;. I guess it&amp;#8217;s kind of a natural thing, especially on the iPad, where you can see a lot more content and have this urge to &amp;#8220;move on&amp;#8221; after entering some data. Apple&amp;#8217;s built-in Apps support it to some extend. For example, if you search for a contact on your iPhone and tap the dark area, covering the &lt;em&gt;UITableView&amp;#8221;, the keyboard is being dismissed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I always managed to get the job done somehow, but was never really satisfied with the solution. Last week, I had to implement this very requirement again and took a step back to think about a more general approach.&lt;/p&gt;

&lt;p&gt;The first step to dimiss the keyboard by tapping outside an input area, is to actually be able to detect the tap. Take a look at Apple&amp;#8217;s approach in Safari.app, when you enter an URL: it adds a dark translucent layer to the content view in order to detect the tap outside the &lt;em&gt;UITextField&lt;/em&gt;. It also prevents accidental taps on any element in the content area.&lt;/p&gt;

&lt;p&gt;You can do the same in your App: In your &lt;em&gt;UIViewController&lt;/em&gt;, you can listen to &lt;em&gt;UIKeyboardDidShowNotification&lt;/em&gt; and &lt;em&gt;UIKeyboardWillHideNotification&lt;/em&gt;, in order to add/remove a &lt;em&gt;UIView&lt;/em&gt; receiving the taps. It doesn&amp;#8217;t necessarily need to be a dark translucent layer like in Safari.app, it could be transparent. I&amp;#8217;ve &lt;a href='http://dlinsin.github.com/2011/05/11/KeyBoardHiddenTextFields.html'&gt;blogged about those to notifications before&lt;/a&gt; and posted some &lt;a href='https://github.com/dlinsin/district9/blob/master/KeyBoardHidden/KeyBoardHidden/KeyBoardHidden/KeyBoardHiddenViewController.m'&gt;sample code on github&lt;/a&gt;, in case you have no idea what I&amp;#8217;m talking about. I&amp;#8217;ve never really though about this before, but it is a general approach, you can take in order to detect taps outside a &lt;em&gt;UITextField&lt;/em&gt; or any other element that takes an input.&lt;/p&gt;

&lt;p&gt;The second step is to actually dismiss the keyboard. So far we only know, if a user taps outside an input area. I always thought there must be a way to tell the keyboard to dismiss, however the &lt;a href='http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html%23//apple_ref/doc/uid/TP40009542-CH5-SW7'&gt;docs&lt;/a&gt; clearly state you are on your own. That means you need to call &lt;em&gt;resignFirstResponder&lt;/em&gt; on the input element currently active. Fortunately, it&amp;#8217;s not too hard to go from detecting a tap to finding and resigning the first responder. I found a &lt;a href='http://stackoverflow.com/questions/1823317/how-do-i-legally-get-the-current-first-responder-on-the-screen-on-an-iphone/1823360#1823360'&gt;neat category on stackoverflow&lt;/a&gt;, which does exactley that:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='k'&gt;@implementation&lt;/span&gt; &lt;span class='nc'&gt;UIView&lt;/span&gt; &lt;span class='nl'&gt;(FindAndResignFirstResponder)&lt;/span&gt;
&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;BOOL&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;findAndResignFirstResponder&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;isFirstResponder&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt; &lt;span class='n'&gt;resignFirstResponder&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;YES&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;     
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UIView&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;subView&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subviews&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;subView&lt;/span&gt; &lt;span class='n'&gt;findAndResignFirstResponder&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;YES&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;NO&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='k'&gt;@end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;a href='https://gist.github.com/1008470' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;You simply add this category to your &lt;em&gt;UIViewController&lt;/em&gt; and it&amp;#8217;s just one method call to go from detecting the tap to dismissing the keyboard.&lt;/p&gt;

&lt;p&gt;The code to listen to the &lt;em&gt;UIKeyboardNotifications&lt;/em&gt; in order to add the &lt;em&gt;UIView&lt;/em&gt; to intercept the taps, as well as resigning the first responder, could go into your AppDelegate or a base &lt;em&gt;UIViewController&lt;/em&gt;. It depends on your needs, I guess. However, I think this is a general approach to handle this requirement in your app.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>iOS 3.x is Dead</title>
   <link href="http://dlinsin.github.com/2011/05/29/iOS3IsDead.html"/>
   <updated>2011-05-29T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/05/29/iOS3IsDead</id>
   <content type="html">&lt;p&gt;In my last post on &lt;a href='http://dlinsin.github.com/2011/05/18/iOSLifecycleAndUILocalNotifications.html'&gt;iOS App Lifecycle and UILocalNotifications&lt;/a&gt;, I wrote about how you can check whether your App is running or has just started from a &lt;em&gt;UILocalNotification&lt;/em&gt;. I use the same code for remote notifications:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;void&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='nl'&gt;application:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UIApplication&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt; 
      &lt;span class='nl'&gt;didReceiveRemoteNotification:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;NSDictionary&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;userInfo&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;applicationState&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;UIApplicationStateActive&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; 
        &lt;span class='n'&gt;DBLog&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Received: %@&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;notification&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;alertBody&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='c1'&gt;// alert, because app is running in foreground&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/997959' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;Well, as it turns out this solution only works with iOS 4.0, since &lt;em&gt;UIApplication.applicationState&lt;/em&gt; is not available on iOS 3.x. I only found this bug yesterday, after our latest App &lt;a href='http://goo.gl/lP9RM'&gt;Cologne Train&lt;/a&gt; was smoothly approved by Apple and is targeted for iOS 3.1.3 (the oldest we have running here).&lt;/p&gt;

&lt;p&gt;Now, don&amp;#8217;t get me wrong! I&amp;#8217;m not writing this to criticise the review process for not catching my bug, although it was an obvious one. It&amp;#8217;s a bug that every static analyzer or API versioning tool could have caught, if it was out to looked for it.&lt;/p&gt;

&lt;p&gt;If Apple wanted to catch bugs, that only occurs on iOS 3.x, I bet they could!&lt;/p&gt;

&lt;p&gt;This is nothing new, I wrote about this &lt;a href='http://dlinsin.blogspot.com/2010/12/why-word-buzz-doesn-support-ios-31.html'&gt;before&lt;/a&gt; and so did &lt;a href='http://www.marco.org/2011/03/24/ios-device-and-os-version-stats-from-instapaper-3-0'&gt;others&lt;/a&gt;. However it&amp;#8217;s worth mentioning it again: the percentage of devices out there running iOS 3.x is tiny. I guess Apple thinks the same way and focuses on other things during review instead.&lt;/p&gt;

&lt;p&gt;I believe with the &lt;a href='http://twitter.com/#!/marcoarment/status/74600722783666176'&gt;latest numbers&lt;/a&gt; and Apple not catching such obvious iOS 3.x related issues, it&amp;#8217;s save to say: &lt;strong&gt;iOS 3.x is dead&lt;/strong&gt;!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>iOS App Lifecycle and UILocalNotifications</title>
   <link href="http://dlinsin.github.com/2011/05/18/iOSLifecycleAndUILocalNotifications.html"/>
   <updated>2011-05-18T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/05/18/iOSLifecycleAndUILocalNotifications</id>
   <content type="html">&lt;p&gt;In my &lt;a href='http://dlinsin.github.com/2011/04/30/UILocalNotification.html'&gt;previous post&lt;/a&gt; on &lt;em&gt;UILocalNotifications&lt;/em&gt;, I wrote about how to reset the badge number on your app icon. This time I&amp;#8217;d like to point out how &lt;em&gt;UILocalNotifications&lt;/em&gt; tie into the iOS lifecycle and a pitfall I ran into, developing furryfishApps lates app. When it comes to the iOS lifecycle in gerneral, I&amp;#8217;d like to refere you to Oliver Drobnik&amp;#8217;s &lt;a href='http://www.cocoanetics.com/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/'&gt;great blog post&lt;/a&gt; a while back.&lt;/p&gt;

&lt;p&gt;All the important methods that tie &lt;em&gt;UILocalNotifications&lt;/em&gt; into your iOS app lifecycle reside in in &lt;em&gt;UIApplicationDelegate&lt;/em&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='c1'&gt;// Tells the delegate when the application has launched and may have additional &lt;/span&gt;
&lt;span class='c1'&gt;// launch options to handle.&lt;/span&gt;
&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;BOOL&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='nl'&gt;application:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UIApplication&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt; &lt;span class='nl'&gt;didFinishLaunchingWithOptions:&lt;/span&gt;
                                                 &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;NSDictionary&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;launchOptions&lt;/span&gt;

&lt;span class='c1'&gt;// Sent to the delegate when a running application receives a local notification.&lt;/span&gt;
&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;void&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='nl'&gt;application:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UIApplication&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt; &lt;span class='nl'&gt;didReceiveLocalNotification:&lt;/span&gt;
                                          &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UILocalNotification&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;notification&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So it looks simple, right? In case you want to do something special, when your app is launching from a button tap on an &lt;em&gt;UILocalNotification&lt;/em&gt; just implement the first method. If you want to handle receiving notifications, while your app is running, e.g. to update a view or display the content, you implement the second method.&lt;/p&gt;

&lt;p&gt;As you can imagine, it turns out not to be that simple after all. I ran into a tricky problem: whenever our App received a &lt;em&gt;UILocalNotification&lt;/em&gt; &amp;#8220;running&amp;#8221; in background and the user taps the button to open the App, &lt;em&gt;application:didReceiveLocalNotification:&lt;/em&gt; on the app delegate was called. If you have implemented &lt;em&gt;application:didReceiveLocalNotification:&lt;/em&gt; to play a sound and display a notification to the user when the App is actually running in the foreground, the same happens if the user taps on the button of the native notification. You probably don&amp;#8217;t want your user to get the same notification and sound twice, especially because he wants to check your App for further information.&lt;/p&gt;

&lt;p&gt;As it turns out, this is intended as Apple&amp;#8217;s documentation of the method states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This method is invoked after application:didFinishLaunchingWithOptions: (if that method is implemented).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So in order to prevent the sound and notification to be played and displayed after launching from a &lt;em&gt;UILocalNotification&lt;/em&gt;, you could simply add some kind of &lt;em&gt;BOOL&lt;/em&gt; to your app delegate in &lt;em&gt;application:didFinishLaunchingWithOptions:&lt;/em&gt; and check it afterwards in &lt;em&gt;application:didReceiveLocalNotification:&lt;/em&gt;. However, &lt;em&gt;application:didFinishLaunchingWithOptions:&lt;/em&gt; is only called when you &amp;#8220;start&amp;#8221; the app, not when your app is becomes active and all the other methods don&amp;#8217;t let you check if you&amp;#8217;ve launched from a &lt;em&gt;UILocalNotification&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;StackOverflow to the rescue! I found a &lt;a href='http://stackoverflow.com/questions/4136333/test-if-app-did-become-active-from-a-uilocalnotification/5708486#5708486'&gt;question&lt;/a&gt; with a neat solution, which works perfectly for me:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;void&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='nl'&gt;application:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UIApplication&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt; &lt;span class='nl'&gt;didReceiveLocalNotification:&lt;/span&gt;
                                        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UILocalNotification&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;notification&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;applicationState&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;UIApplicationStateActive&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; 
        &lt;span class='n'&gt;DBLog&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Received: %@&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;notification&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;alertBody&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='c1'&gt;// alert, because app is running in foreground&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/978155' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;It turns out, that &lt;em&gt;UIApplication.applicationState&lt;/em&gt; is only active when the app is running in foreground. This is a neat way to check if your app has just launched from a &lt;em&gt;UILocalNotification&lt;/em&gt; or is already active.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>UITextFields hidden by keyboard</title>
   <link href="http://dlinsin.github.com/2011/05/11/KeyBoardHiddenTextFields.html"/>
   <updated>2011-05-11T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/05/11/KeyBoardHiddenTextFields</id>
   <content type="html">&lt;p&gt;In almost every iOS app I developed so far I came across the situation where multiple UITextFields on the screen are hidden behind the keyboard. I almost always developed a custom solution, since I didn&amp;#8217;t know any better. A couple of weeks ago, again facing the same problem, I came across a &lt;a href='http://atastypixel.com/blog/a-drop-in-universal-solution-for-moving-text-fields-out-of-the-way-of-the-keyboard/'&gt;blog post&lt;/a&gt; by Michael Tyson, which features a drop-in UIScrollView component to handle the problem. Unfortunately, he didn&amp;#8217;t reveal in his post, that this is also &lt;a href='http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html%23//apple_ref/doc/uid/TP40009542-CH5-SW7'&gt;Apple&amp;#8217;s proposed solution&lt;/a&gt; to the problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When asked to display the keyboard, the system slides it in from the bottom of the screen and positions it over your application’s content. Because it is placed on top of your content, it is possible for the keyboard to be placed on top of the text object that the user wanted to edit. When this happens, you must adjust your content so that the target object remains visible.&lt;/p&gt;

&lt;p&gt;Adjusting your content typically involves temporarily resizing one or more views and positioning them so that the text object remains visible. The simplest way to manage text objects with the keyboard is to embed them inside a UIScrollView object (or one of its subclasses like UITableView). When the keyboard is displayed, all you have to do is reset the content area of the scroll view and scroll the desired text object into position. Thus, in response to a UIKeyboardDidShowNotification, your handler method would do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get the size of the keyboard.&lt;/li&gt;

&lt;li&gt;Adjust the bottom content inset of your scroll view by the keyboard height.&lt;/li&gt;

&lt;li&gt;Scroll the target text field into view.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you look at Michael&amp;#8217;s &lt;a href='https://github.com/michaeltyson/TPKeyboardAvoiding'&gt;code on github&lt;/a&gt; you can see, that he went along to creat a set of custom base classes handling those three steps, that Apple suggest to do. I suggest to go, check it out and use it if you can!&lt;/p&gt;

&lt;p&gt;In case you cannot use it or don&amp;#8217;t want to, I created a small sample project for myself to understand what Apple is suggesting. You can find it &lt;a href='https://github.com/dlinsin/district9/tree/master/KeyBoardHidden'&gt;on github&lt;/a&gt;. Almost all the code is from the Apple&amp;#8217;s documentation. It&amp;#8217;s the bare minimum without any animation or fancy schmancy design, but I believe it gives you an idea of how to apply it to your code.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Reset App Icon Badge with UILocalNotification</title>
   <link href="http://dlinsin.github.com/2011/04/30/UILocalNotification.html"/>
   <updated>2011-04-30T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/04/30/UILocalNotification</id>
   <content type="html">&lt;p&gt;For our new super secret project at &lt;a href='http://furryfishapps.com' title='furryfishApps'&gt;furryfishApps&lt;/a&gt;, we are heavily using &lt;em&gt;&lt;a href='http://developer.apple.com/library/ios/#documentation/iphone/Reference/UILocalNotification_Class/Reference/Reference.html' title='Apple&amp;apos;s docs on UILocalNotification'&gt;UILocalNotification&lt;/a&gt;&lt;/em&gt; and the badge on our App&amp;#8217;s icon.&lt;/p&gt;

&lt;p&gt;Just to quickly revisit: when a &lt;em&gt;UILocalNotification&lt;/em&gt; is fired, it&amp;#8217;ll set the badge to the number, that you previously defined like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='n'&gt;UILocalNotification&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;notification&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;UILocalNotification&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='n'&gt;notification&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;applicationIconBadgeNumber&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='c1'&gt;// TODO schedule notification&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/949534' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;While trying to remove the badge, I found that there is no documentation on this whatsoever. You might think it should be easy, just set the property &lt;em&gt;applicationIconBadgeNumber&lt;/em&gt; to 0, however here&amp;#8217;s what &lt;em&gt;UILocalNotification&lt;/em&gt;&amp;#8217;s documentation says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The default value is 0, which means &amp;#8220;no change.” The application should use this property’s value to increment the current icon badge number, if any.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, that means the badge is not removed when setting the property &lt;em&gt;applicationIconBadgeNumber&lt;/em&gt; to 0, &lt;strong&gt;instead you need to set it -1&lt;/strong&gt;. As soon as the &lt;em&gt;UILocalNotification&lt;/em&gt; is fired, the badge is removed from the App&amp;#8217;s icon.&lt;/p&gt;

&lt;p&gt;Would be nice to have that in the documentation, so I filed radar://9357622.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>DLWebView - a drop-in browser component</title>
   <link href="http://dlinsin.github.com/2011/04/24/DLWebView.html"/>
   <updated>2011-04-24T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/04/24/DLWebView</id>
   <content type="html">&lt;p&gt;A couple of weeks ago, I had to implement a browser component in 4 different Apps at &lt;a href='http://grandcentrix.com'&gt;work&lt;/a&gt;. I went through the hassel of implementing it separately each time, although they basically had the same requirements. Last weekend I went the extra mile to bake a component, which you can use in your code, in case you need to display a website.&lt;/p&gt;

&lt;p&gt;Hello World - &lt;a href='http://github.com/dlinsin/DLWebView'&gt;DLWebView&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DLWebView&lt;/strong&gt; is a &lt;em&gt;UIViewController&lt;/em&gt; subclass, which you can use in conjunction with a &lt;em&gt;UINavigationController&lt;/em&gt;. It features a refresh button, back/forward buttons as well as a title label. Those buttons are added to the &lt;em&gt;UINavigationBar&lt;/em&gt;, when DLWebView is loaded.&lt;/p&gt;

&lt;p&gt;If you add a &lt;em&gt;UIBarButtonItem&lt;/em&gt; to &lt;strong&gt;DLWebView&lt;/strong&gt;, when setting up the &lt;em&gt;UINavigationController&lt;/em&gt; and hook it up to&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;IBAction&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='nl'&gt;showUrlField:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;sender&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and you&amp;#8217;ll get a flashy &lt;em&gt;UITextField&lt;/em&gt; to handle editing URLs. However, if you only have one website to display, it&amp;#8217;s not mandatory to enable this feature.&lt;/p&gt;
&lt;object height='385' width='480'&gt;&lt;param name='movie' value='http://www.youtube.com/v/RrdGWb8qJ4Q?fs=1&amp;amp;hl=en_US' /&gt;&lt;param name='allowFullScreen' value='true' /&gt;&lt;param name='allowscriptaccess' value='always' /&gt;&lt;embed src='http://www.youtube.com/v/RrdGWb8qJ4Q?fs=1&amp;amp;hl=en_US' allowfullscreen='true' type='application/x-shockwave-flash' allowscriptaccess='always' height='385' width='480' /&gt;&lt;/object&gt;
&lt;p&gt;&lt;strong&gt;DLWebView&lt;/strong&gt; works in portrait and in landscape mode (check out the video above). Once a page is loading, you can see the URL displayed in the title, which changes to the title of the website once loaded completly. It&amp;#8217;s iOS 3.x compatible, so no worries about breaking exisiting Apps.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s still some stuff to work on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there&amp;#8217;s a basic URL validation implemented, however it&amp;#8217;s far from being perfect and I&amp;#8217;m thinking of removing it entirely.&lt;/li&gt;

&lt;li&gt;the dependency on &lt;em&gt;UINavigationController&lt;/em&gt; is certainly not be the best solution, so I&amp;#8217;m looking into removing that&lt;/li&gt;

&lt;li&gt;the solution of using a &lt;em&gt;UIBarButtonItme&lt;/em&gt; for bringing up the text field to edit URLs is not ideal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;d love for folks out there to &lt;a href='http://github.com/dlinsin/DLWebView'&gt;help&lt;/a&gt; me make this a first-class component to use, when you need to display websites in your App.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>ATMHud</title>
   <link href="http://dlinsin.github.com/2011/03/24/ATMHud.html"/>
   <updated>2011-03-24T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/03/24/ATMHud</id>
   <content type="html">&lt;p&gt;I recently started using &lt;a href='https://github.com/atomton/ATMHud' title='ATMHud on github'&gt;ATMHud&lt;/a&gt;, a great iOS library to indicate activity and short notifications in an App via HUDs. I want to give you a little overview of how ATMHud can look like and how it is used in your code.&lt;/p&gt;

&lt;p&gt;Most of the samples can be found in the &lt;a href='https://github.com/atomton/ATMHud/blob/master/Classes/DemoViewController.m' title='DemoViewController on github'&gt;DemoViewController&lt;/a&gt;, which comes along with the code. However, I think it gives you a better understanding of what it&amp;#8217;s like to use ATMHud, if they are highlighted here. Let&amp;#8217;s dive right into it:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='cp'&gt;#import &amp;quot;ATMHud.h&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;ATMHud&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nl'&gt;initWithDelegate:&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt; &lt;span class='nl'&gt;addSubview:&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='nl'&gt;setCaption:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Please wait...&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='nl'&gt;setActivity:&lt;/span&gt;&lt;span class='n'&gt;YES&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='n'&gt;show&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/882722' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;This is one of the simplest samples to display a ATMHud in your code. You simply instantiate and add it to the view the HUD is supposed to be displayed on top of. The API to configure the style is as simple as calling a method to set the message and enable an activity. This is how it looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-03-24-simple.png' alt='Simple HUD' /&gt;&lt;/p&gt;

&lt;p&gt;The next sample is a little bit more sophisticated, but shows the power of ATMHud.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='cp'&gt;#import &amp;quot;ATMHud.h&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;ATMHud&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nl'&gt;initWithDelegate:&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt; &lt;span class='nl'&gt;addSubview:&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='nl'&gt;setCaption:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Successfully saved&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='nl'&gt;setImage:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;UIImage&lt;/span&gt; &lt;span class='nl'&gt;imageNamed:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;19-check&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='n'&gt;show&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='nl'&gt;hideAfter:&lt;/span&gt;&lt;span class='mf'&gt;2.0&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/882723' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;This HUD consist of a message, just like the previous sample. In addition to that, an image is set, which is automatically displayed below the configured message. The really neat thing here is that the HUD is automatically dimissed after two seconds. This way you can display little flash notifications, which can help users to better understand your App. This is what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-03-24-advanced.png' alt='HUD with image' /&gt;&lt;/p&gt;

&lt;p&gt;The next sample is a tad bit more complicated, but also a lot more powerful. Imagine you want to let your user know that his task is being processed at the moment. As soon as the work is complete, you want to notifiy him again. In ATMHud you can do just that using &lt;em&gt;ATMHudQueueItems&lt;/em&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='cp'&gt;#import &amp;quot;ATMHud.h&amp;quot;&lt;/span&gt;
&lt;span class='cp'&gt;#import &amp;quot;ATMHudQueueItem.h&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;ATMHud&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nl'&gt;initWithDelegate:&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt; &lt;span class='nl'&gt;addSubview:&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='n'&gt;ATMHudQueueItem&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;item&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;ATMHudQueueItem&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='n'&gt;item&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;caption&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;Saving...&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;item&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;showActivity&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;YES&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='nl'&gt;addQueueItem:&lt;/span&gt;&lt;span class='n'&gt;item&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;item&lt;/span&gt; &lt;span class='n'&gt;release&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='n'&gt;item&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;ATMHudQueueItem&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='n'&gt;item&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;caption&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;Successfully saved&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;item&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;showActivity&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;NO&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;item&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;image&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;UIImage&lt;/span&gt; &lt;span class='nl'&gt;imageNamed:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;19-check&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='nl'&gt;addQueueItem:&lt;/span&gt;&lt;span class='n'&gt;item&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;item&lt;/span&gt; &lt;span class='n'&gt;release&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='n'&gt;startQueue&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='c1'&gt;// after a while&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;hud&lt;/span&gt; &lt;span class='n'&gt;showNextInQueue&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/882725' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;&lt;img src='/images/2011-03-24-queue1.png' alt='Queue of HUDs - 1st' /&gt; &lt;img src='/images/2011-03-24-queue2.png' alt='Queue of HUDs - 2nd' /&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s quite easy to understand how this works and you can see how powerful this concept is. We setup &lt;em&gt;ATMHudQueueItem&lt;/em&gt; instances, which can be configured with the same options as a simple &lt;em&gt;ATMHud&lt;/em&gt; instance. You can set an image, sound and acitivty indicator. You add those queue items to the &lt;em&gt;ATMHud&lt;/em&gt; instance and start it at some point. As soon as the first step of your process is done, you can show the next HUD in the queue.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s much more to &lt;a href='https://github.com/atomton/ATMHud' title='ATMHud on github'&gt;ATMHud&lt;/a&gt; as highlighted here. For example you can add a sound to your HUD, there&amp;#8217;s a way to display beautiful progress bars or you can configure the position of the activity indicator. If you need a better way to notify the users of your App, you should really have a look at ATMHud by &lt;a href='http://www.atomcraft.de/' title='atomcraft iOS development'&gt;atomcraft&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Don't use MainWindow.xib with Autorotation</title>
   <link href="http://dlinsin.github.com/2011/03/14/autorotation.html"/>
   <updated>2011-03-14T00:00:00-07:00</updated>
   <id>http://dlinsin.github.com/2011/03/14/autorotation</id>
   <content type="html">&lt;p&gt;Working on &lt;a href='http://furryfishapps.com' title='furryfishApps'&gt;furryfishApps&amp;#8217;&lt;/a&gt; new super secret project, I came across a strange problem, which not even &lt;a href='http://stackoverflow.com' title='stackoverflow'&gt;stackoverflow&lt;/a&gt; had a solution for. At least I couldn&amp;#8217;t find it.&lt;/p&gt;

&lt;p&gt;When using the standard Apple template to create an iOS framework, Xcode creates, along with other stuff, a &lt;em&gt;MainWindow.xib&lt;/em&gt;, which contains your &lt;em&gt;UIWindow&lt;/em&gt; and is used to create your AppDelegate. Since its&amp;#8217; already hooked up to your &lt;em&gt;Info.plist&lt;/em&gt; and works out of the box, I never bothered to question this construct - until today.&lt;/p&gt;

&lt;p&gt;I noticed that our new App, when rotated has some weird effects at the bottom of the screen. It didn&amp;#8217;t appear smooth, almost a little lagging. Since a picture tells more than my attempt to explain:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-03-20-autorotation-1.png' alt='Weird effects when autorotating' /&gt;&lt;/p&gt;

&lt;p&gt;Since I&amp;#8217;m using a pimped version of &lt;a href='http://github.com/dlinsin/BCTabBarController' title='BCTabBarController fork on github'&gt;BCTabBarController&lt;/a&gt;, my first thought was that it must be the root of all evil. Fortunately, I was wrong! The sample coming with BCTabBarController doesn&amp;#8217;t show those effects. I decided to set up a brand new projects with Apple view-based template. After integrating and setting up BCTabBarController, the same effects as in our App appeared. The projects were almost identical, so how could this be?&lt;/p&gt;

&lt;p&gt;The only difference between the two projects was the setup of AppDelegate and its &lt;em&gt;UIWindow&lt;/em&gt;. Apple&amp;#8217;s template added a &lt;em&gt;NSMainNibFile&lt;/em&gt; key and MainWindow.xib value to the &lt;em&gt;Info.plist&lt;/em&gt;. Furthermore there&amp;#8217;s an &lt;em&gt;IBOutlet&lt;/em&gt; in the AppDelegate, which is hooked up to the &lt;em&gt;UIWindow&lt;/em&gt; instance, configured in &lt;em&gt;MainWindow.xib&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The BCTabBarController sample project on the other hand was configured &amp;#8220;manually&amp;#8221;. The &lt;em&gt;UIWindow&lt;/em&gt; instance was created in the AppDelegate like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;window&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[[&lt;/span&gt;&lt;span class='n'&gt;UIWindow&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nl'&gt;initWithFrame:&lt;/span&gt;
              &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;UIScreen&lt;/span&gt; &lt;span class='n'&gt;mainScreen&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='n'&gt;bounds&lt;/span&gt;&lt;span class='p'&gt;]]&lt;/span&gt; &lt;span class='n'&gt;autorelease&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/868321' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;There was no MainWindow.xib, so no need for a corresponding key/value pair in the &lt;em&gt;Info.plist&lt;/em&gt;. The AppDelegate is configured in the file &lt;em&gt;main.m&lt;/em&gt; like this:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;retVal&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;UIApplicationMain&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;argc&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;argv&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;EXAppDelegate&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;a href='https://gist.github.com/3512b737fd34a3e75a6a' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;After applying those changes to our new project, I was able to remove the weird effects and there&amp;#8217;s a smooth autorotation experience now:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-03-20-autorotation-2.png' alt='Smooth autorotation' /&gt;&lt;/p&gt;

&lt;p&gt;Honestly, I have no idea what the cause of this might be. Looking at the configuration of &lt;em&gt;UIWindow&lt;/em&gt; instantiated by &lt;em&gt;MainWindow.xib&lt;/em&gt;, there&amp;#8217;s no difference to the one set up manually. I&amp;#8217;m grateful for any clues, however, at the moment I&amp;#8217;m just happy that I solved this issue.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>JSON frameworks API comparison</title>
   <link href="http://dlinsin.github.com/2011/03/10/json-frameworks-api-comparison.html"/>
   <updated>2011-03-10T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/03/10/json-frameworks-api-comparison</id>
   <content type="html">&lt;p&gt;There are dozens of iOS compatible JSON frameworks aka parsers. It&amp;#8217;s awesome to have the ability to choose between so many different frameworks, however there are differences in terms of performance, API and licensing. I&amp;#8217;ll take a highlevel peek at couple of them in terms of their API and how to use them in your project. I&amp;#8217;ll only highlight and compare the JSON consuming part of the API, although serialization works similarly.&lt;/p&gt;

&lt;p&gt;All of the frameworks presented here, are released under a license which allows you to use them in closed-source projects, so no problem here. Please keep in mind, that I don&amp;#8217;t factor in performance. If you are interested there are &lt;a href='http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg61077.html' title='JSON framework performance'&gt;lots&lt;/a&gt; of &lt;a href='http://www.cocoanetics.com/2011/03/json-versus-plist-the-ultimate-showdown/' title='JSON framework performance'&gt;comparisons&lt;/a&gt; out there.&lt;/p&gt;

&lt;p&gt;The first framework I&amp;#8217;d like to highlight is &lt;a href='https://github.com/gabriel/yajl-objc' title='YAJL on gihub'&gt;YAJL&lt;/a&gt; (Yet Another JSON Library). I used YAJL in a &lt;a href='http://itunes.apple.com/us/artist/david-linsin/id362714030' title='David Linsin on iTunes'&gt;couple of projects&lt;/a&gt; and I really like its approach. It&amp;#8217;s available for Mac and iOS. In order to use it in your project, you can either include it as a static library or add the source code to your Xcode project. In the latter case, you&amp;#8217;ll need to add other linker flags in your target in order to use YAIL.&lt;/p&gt;

&lt;p&gt;From an &lt;a href='http://gabriel.github.com/yajl-objc/' title='API docs'&gt;API&lt;/a&gt; point of view, YAIL comes with a bunch of categories on &lt;em&gt;NSString&lt;/em&gt; or &lt;em&gt;NSData&lt;/em&gt;, helping you to transform the JSON string into various Objective-C data types. It looks something like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='cp'&gt;#import &amp;lt;YAJLiOS/YAJL.h&amp;gt;&lt;/span&gt;
&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;[1, 2, 3]&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;NSArray&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;arrayFromString&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='n'&gt;yajl_JSON&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/857288' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;I really like YAJL&amp;#8217;s transparent approach using categories, although using it as a static library and configuring linker flags can be a &lt;a href='http://dlinsin.blogspot.com/2010/05/don-forget-your-linker-flags.html' title='blog post on linker flags'&gt;source of error&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The next framework I&amp;#8217;d like to talk about is &lt;a href='https://github.com/johnezang/JSONKit' title='JSONKit on gihub'&gt;JSONKit&lt;/a&gt;. I&amp;#8217;m using it on my current project at work and so far I&amp;#8217;m quite happy. Just like YAJL, JSONKit comes with categories on &lt;em&gt;NSString&lt;/em&gt; and &lt;em&gt;NSData&lt;/em&gt;. In addition to that, it has an explicit parsing interface to create objects from those two data types.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='cp'&gt;#import &amp;quot;JSONKit.h&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;[1, 2, 3]&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;NSArray&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;arrayFromString&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='n'&gt;objectFromJSONString&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/857294' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;I like JSONKit, especially because it manages to provide an easy to use API. It also doesn&amp;#8217;t hurt, that it &lt;a href='http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg61077.html' title='JSON framework performance'&gt;seems&lt;/a&gt; to be quite fast.&lt;/p&gt;

&lt;p&gt;At work we use &lt;a href='https://github.com/stig/json-framework' title='json-framework on github'&gt;json-framework&lt;/a&gt; a lot. It doesn&amp;#8217;t stand out much from the frameworks discussed before. The only real difference is, it has been around for &lt;a href='https://github.com/stig/json-framework/commit/108b9ca38dc2fd8ad31db078cfc71b3b4ab10d13' title='commit on github'&gt;quite a while&lt;/a&gt;. Just like JSONKit it provides an explicit interface or categories to parse JSON from &lt;em&gt;NSString&lt;/em&gt; and &lt;em&gt;NSData&lt;/em&gt;. Let&amp;#8217;s look at the same example of the previously discussed frameworks:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='cp'&gt;#import &amp;quot;JSON.h&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;[1, 2, 3]&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;NSArray&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;arrayFromString&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='n'&gt;JSONValue&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/860623' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;A nice feature of json-framework&amp;#8217;s explicit parser interface is the &lt;a href='http://stig.github.com/json-framework/api/interfaceSBJsonParser.html#a0378b4ce99a1caeddc4a05da37ca4ffa' title='api docs on github'&gt;configuration of parsing depth&lt;/a&gt;. It could be useful, if you have to parse large JSON structures and only need the top level objects.&lt;/p&gt;

&lt;p&gt;The last framework I want to peek at is &lt;a href='https://github.com/TouchCode/TouchJSON' title='TouchJSON on github'&gt;TouchJSON&lt;/a&gt;. As with json-framework, I&amp;#8217;ve never used this one in production myself. The only way to get an overview is by looking at a couple of samples and running them in an Xcode project. In order to use TouchJSON, you simply have to include the source in your project. The sample code used to previously illustrate how to use the framework looks a little different:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='cp'&gt;#import &amp;quot;CJSONDeserializer.h&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;[1, 2, 3]&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;NSData&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;jsonData&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;JSONString&lt;/span&gt; &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='n'&gt;NSError&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;NSArray&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;array&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;CJSONDeserializer&lt;/span&gt; &lt;span class='n'&gt;deserializer&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nl'&gt;deserializeAsArray:&lt;/span&gt;&lt;span class='n'&gt;jsonData&lt;/span&gt; 
                &lt;span class='nl'&gt;error:&lt;/span&gt;&lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;error&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/860676' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;In contrast to all other frameworks, TouchJSON only supports a category to create a &lt;em&gt;NSDictionary&lt;/em&gt;. Everything else needs to be done using the explicit interface &lt;em&gt;CJSONDeserializer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As you can see, almost all API&amp;#8217;s are used the same way. They all provide categories, except for TouchJSON. You can simply use iOS&amp;#8217; datatypes to retrieve native datastructures from JSON. I like categories, especially when used in such a way as the JSON frameworks presented here. It just feels natural to call &lt;em&gt;objectFromJSONString&lt;/em&gt; on a &lt;em&gt;NSString&lt;/em&gt; containing JSON.&lt;/p&gt;

&lt;p&gt;There is no clear winner, but I think JSONKit would be my framework of choice, if I had to pick. I love the transparent, intuitive approach of its API and for me that&amp;#8217;s more important than other aspects of a framework.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Different country - Different App Store</title>
   <link href="http://dlinsin.github.com/2011/03/03/different-country-different-appstore.html"/>
   <updated>2011-03-03T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/03/03/different-country-different-appstore</id>
   <content type="html">&lt;p&gt;The business of Apple&amp;#8217;s App Store works different in each country. For most part, I think it&amp;#8217;s because the customer&amp;#8217;s mindset is quite different.&lt;/p&gt;

&lt;p&gt;Look at Germany and the US for example. In Germany not everyone owns a credit card. I know a lot of people, which don&amp;#8217;t have one and are happy about it. As far as I can tell, it&amp;#8217;s a whole different ball game in the US. Most people have a credit card or even multiple. That alone doesn&amp;#8217;t say much about why the App Store works different in those two countries. However, it gives you an idea, how people think about money and how willing they are to spend it on your App.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s take a look at another sign of the differences in terms of App Stores: customer ratings. Apple&amp;#8217;s App Store, both on iOS and Mac, lets you rate Apps, based on a number of stars. In addition to that, you can add a comment to further express what you like or don&amp;#8217;t like about an App. I&amp;#8217;ve always taken ratings quite seriously and I hate the fact, that you cannot respond to customers having issues with your App, but that&amp;#8217;s a topic for another blog post.&lt;/p&gt;

&lt;p&gt;Take a look at the ratings of the recently released Apple &lt;a href='http://www.apple.com/mac/facetime/' title='Apple Face Time for Mac'&gt;Face Time App for Mac&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-03-03-appstore-de.png' alt='Face Time Ratings Germany' /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-03-03-appstore-us.png' alt='Face Time Ratings US' /&gt;&lt;/p&gt;

&lt;p&gt;The first screenshot obviously shows ratings of the &lt;a href='http://itunes.apple.com/de/app/facetime/id414307850?mt=12' title='German App Store'&gt;German App Store&lt;/a&gt; on Mac, the second of the &lt;a href='http://itunes.apple.com/us/app/facetime/id414307850?mt=12' title='US App Store'&gt;US&lt;/a&gt;. You might think those ratings are the result of a technical problem, maybe only happening in Germany and not the US. Let me tell you, they are not! Most of the comments in the German App Store, below the ratings, complain about Apple charging 0,79€ resp. $0.99!&lt;/p&gt;

&lt;p&gt;It think this is a conclusive example, that the App Store model in Germany is so much different from the one in the US! If you read the comments below the ratings, you can see, that customers in Germany are thinking twice about whether to spend 0.79€ on an App or not.&lt;/p&gt;

&lt;p&gt;So what can you as a developer or small iOS shop do about this? Unfortunately, there isn&amp;#8217;t much you can do. Apple doesn&amp;#8217;t let you set different prices in each country. You are basically stuck with the workaround of submitting two different Apps with the same feature set to the App Store and limit its availability to certain countries. That way you can individually configure prices. However, that leaves you with maintain multiple Apps - nothing I would want to do. I&amp;#8217;d rather live with the same price across different countries, until Apple comes up with a solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Seems like there was a &lt;a href='https://twitter.com/#!/olebegemann/status/154583220246151168'&gt;technical issue&lt;/a&gt; with the German version of Face Time, which basically renders the example for my case invalid. However, I still think the mindset of customers in each country is different, although I don&amp;#8217;t have any example to make a case.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Hello World</title>
   <link href="http://dlinsin.github.com/2011/03/01/hello-world.html"/>
   <updated>2011-03-01T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/03/01/hello-world</id>
   <content type="html">&lt;p&gt;When developers are talking about &lt;a href='http://en.wikipedia.org/wiki/Hello_world_program' title='Wikipedia on Hello World'&gt;&amp;#8220;Hello World&amp;#8221;&lt;/a&gt;, they usually talk about their first steps in a new programming language. When I say &amp;#8220;Hello World&amp;#8221; today, I am talking about my first steps in mobile development.&lt;/p&gt;

&lt;p&gt;If you are reading this, you are probably aware of my &lt;a href='http://furryfishApps.com/wordbuzz' title='furryfishApps - Word Buzz'&gt;other mobile endavours&lt;/a&gt; and might be asking yourself right now: why &amp;#8220;Hello World&amp;#8221;? Why first steps? Well, today is my first day of iOS-only and full time mobile development at &lt;a href='http://grandcentrix.net' title='GrandCentrix GmbH'&gt;GrandCentrix GmbH&lt;/a&gt; in Cologne.&lt;/p&gt;

&lt;p&gt;GrandCentrix is your full service provider for mobile solutions. We provide ready to use mobile marketing, productivity and customer-service Apps for various platforms and industries.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m really excited about this change! My spare time passion for iOS development turns into my day job, which means I can put a 120% of my efforts and concentration into building awesome Apps.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>ShareKit Pimping</title>
   <link href="http://dlinsin.github.com/2011/02/15/sharekit-pimping.html"/>
   <updated>2011-02-15T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/02/15/sharekit-pimping</id>
   <content type="html">&lt;p&gt;A couple of months ago, I &lt;a href='http://dlinsin.blogspot.com/2010/11/word-buzz-getting-better-twitter.html'&gt;improved Word Buzz' Twitter sharing feature&lt;/a&gt; significantly, by leveraging a &lt;a href='https://github.com/dlinsin/iphone-twitter'&gt;tweaked version&lt;/a&gt; of an existing framework. Unfortunately, I had only heard of &lt;a href='http://getsharekit.com'&gt;ShareKit&lt;/a&gt; at that time, that&amp;#8217;s the reason why I decided to implement my own solution!&lt;/p&gt;

&lt;p&gt;In case you don&amp;#8217;t know about ShareKit or like me only heard about it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SharKit adds full sharing capabilities to your App. It&amp;#8217;s a drop-in library, which supports services like Twitter, Facebook, Instapaper and many more. You can share links, text and pictures with a customizable user interface. It evens queues shared items until an internet connection is available.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;SharKit is awesome and I really regret not using it to add Twitter sharing to &lt;a href='http://itunes.apple.com/app/word-buzz/id388372038?mt=8'&gt;Word Buzz&lt;/a&gt;. It has a well documented API and is really easy to extend, there&amp;#8217;s even a step-by-step guide on ShakreKit&amp;#8217;s website, which describes the process. I followed that guide to add &lt;a href='https://github.com/dlinsin/ShareKit'&gt;TwitPic and yfrog capability&lt;/a&gt; to ShareKit for one of our next &lt;a href='http://twitter.com/furryfishApps'&gt;furryfishApps&lt;/a&gt; projects and that&amp;#8217;s what I&amp;#8217;d like to write about in this post.&lt;/p&gt;

&lt;p&gt;ShareKit comes with built-in Twitter support, which you can find in &lt;em&gt;SHKTwitter&lt;/em&gt; and its authentication form &lt;em&gt;SHKTwitterForm&lt;/em&gt;. It uses &lt;a href='http://bit.ly'&gt;bit.ly&lt;/a&gt; to share images, which has a similar API as TwitPic and yfrog. I piggybacked on that implementation, however dropped oAuth support in favor of xAuth.&lt;/p&gt;

&lt;p&gt;I know there are &lt;a href='http://hueniverse.com/2010/06/xauth-a-terrible-horrible-no-good-very-bad-idea/'&gt;a lot of discussions&lt;/a&gt; on xAuth, however I found it the &lt;a href='http://www.reynoldsftw.com/2010/03/using-xauth-an-alternate-oauth-from-twitter/'&gt;easiest way&lt;/a&gt; to provide the most benefit for iPhone App users, without compromising security in a hurtful way. In order to get your iPhone App ready to use xAuth with Twitter, you need to sign up at &lt;a href='http://developer.twitter.com/'&gt;http://developer.twitter.com/&lt;/a&gt;. I described the process in a &lt;a href='http://dlinsin.blogspot.com/2010/11/word-buzz-getting-better-twitter.html'&gt;previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The previously mentioned class &lt;em&gt;SHKTwitter&lt;/em&gt; inherits from &lt;em&gt;SHKOAuthSharer&lt;/em&gt;, which does all the heavy lifting in terms of authentication for you! All you need to do is hook into the API calls and customize your authentication screen:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;NSArray&lt;/span&gt; &lt;span class='nl'&gt;arrayWithObjects:&lt;/span&gt;
  &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;SHKFormFieldSettings&lt;/span&gt; &lt;span class='nl'&gt;label:&lt;/span&gt;&lt;span class='n'&gt;SHKLocalizedString&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Username&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nl'&gt;key:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;username&amp;quot;&lt;/span&gt; 
    &lt;span class='nl'&gt;type:&lt;/span&gt;&lt;span class='n'&gt;SHKFormFieldTypeText&lt;/span&gt; &lt;span class='nl'&gt;start:&lt;/span&gt;&lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt;
  &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;SHKFormFieldSettings&lt;/span&gt; &lt;span class='nl'&gt;label:&lt;/span&gt;&lt;span class='n'&gt;SHKLocalizedString&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Password&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nl'&gt;key:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;password&amp;quot;&lt;/span&gt; 
    &lt;span class='nl'&gt;type:&lt;/span&gt;&lt;span class='n'&gt;SHKFormFieldTypePassword&lt;/span&gt; &lt;span class='nl'&gt;start:&lt;/span&gt;&lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt;
  &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;SHKFormFieldSettings&lt;/span&gt; &lt;span class='nl'&gt;label:&lt;/span&gt;&lt;span class='n'&gt;SHKLocalizedString&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Send to Twitter&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; 
    &lt;span class='nl'&gt;key:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;sendToTwitter&amp;quot;&lt;/span&gt; &lt;span class='nl'&gt;type:&lt;/span&gt;&lt;span class='n'&gt;SHKFormFieldTypeSwitch&lt;/span&gt; &lt;span class='nl'&gt;start:&lt;/span&gt;&lt;span class='n'&gt;SHKFormFieldSwitchOn&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt;&lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/827260' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;So let&amp;#8217;s say the user wants to share a picture, taps on the share icon and select TwitPic. He authenticates after being prompt for his Twitter credentials. When the authentication was successful, you want to show some sort of form to your users, where they can enter a comment or in case of Twitter, their status. You can totally customize the UI, without any dependency to ShareKit. In fact &lt;em&gt;SHKTwitterForm&lt;/em&gt;, ShareKits built-in Twitter form, is a simple &lt;em&gt;UIViewController&lt;/em&gt; with its delegate set to &lt;em&gt;SHKTwitter&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The actual sharing part of the code is as straight forward as the rest of ShareKit. It&amp;#8217;s a little verbose, but once your understood the concept, it&amp;#8217;s easy to extend:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;void&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;sendImage&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;

&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;oauthHeader&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt; &lt;span class='n'&gt;oauthHeader&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='n'&gt;NSURL&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;serviceURL&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;NSURL&lt;/span&gt; &lt;span class='nl'&gt;URLWithString:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;http://yfrog.com/api/xauth_upload&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='n'&gt;OAMutableURLRequest&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;OAMutableURLRequest&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nl'&gt;initWithURL:&lt;/span&gt;&lt;span class='n'&gt;serviceURL&lt;/span&gt;
&lt;span class='nl'&gt;consumer:&lt;/span&gt;&lt;span class='n'&gt;super&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;consumer&lt;/span&gt;
&lt;span class='nl'&gt;token:&lt;/span&gt;&lt;span class='n'&gt;super&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;accessToken&lt;/span&gt;
&lt;span class='nl'&gt;realm:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;http://api.twitter.com/&amp;quot;&lt;/span&gt;
&lt;span class='nl'&gt;signatureProvider:&lt;/span&gt;&lt;span class='n'&gt;super&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;signatureProvider&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='n'&gt;prepare&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='nl'&gt;setValue:&lt;/span&gt;&lt;span class='nb'&gt;nil&lt;/span&gt; &lt;span class='nl'&gt;forHTTPHeaderField:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Authorization&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='nl'&gt;setHTTPMethod:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='nl'&gt;setValue:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;https://api.twitter.com/1/account/verify_credentials.json&amp;quot;&lt;/span&gt; 
  &lt;span class='nl'&gt;forHTTPHeaderField:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;X-Auth-Service-Provider&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='nl'&gt;setValue:&lt;/span&gt;&lt;span class='n'&gt;oauthHeader&lt;/span&gt; 
  &lt;span class='nl'&gt;forHTTPHeaderField:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;X-Verify-Credentials-Authorization&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;boundary&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;a21ff70823f9&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;contentType&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='nl'&gt;stringWithFormat:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;multipart/form-data; &lt;/span&gt;
                                                  &lt;span class='n'&gt;boundary&lt;/span&gt;&lt;span class='o'&gt;=%&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;,boundary];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='nl'&gt;setValue:&lt;/span&gt;&lt;span class='n'&gt;contentType&lt;/span&gt; &lt;span class='nl'&gt;forHTTPHeaderField:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='n'&gt;NSMutableData&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;NSMutableData&lt;/span&gt; &lt;span class='n'&gt;data&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='nl'&gt;stringWithFormat:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;--%@&lt;/span&gt;&lt;span class='se'&gt;\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;boundary&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; 
  &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Content-Disposition: form-data; name=&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s'&gt;key&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;\r\n\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;yfrogAPIKey&lt;/span&gt; &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='nl'&gt;stringWithFormat:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;--%@&lt;/span&gt;&lt;span class='se'&gt;\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;boundary&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; 
  &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Content-Disposition: form-data; name=&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s'&gt;media&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s'&gt;; &lt;/span&gt;
  &lt;span class='n'&gt;filename&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='err'&gt;\&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;upload.jpg&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;Content-Type: image/jpg&lt;/span&gt;&lt;span class='se'&gt;\r\n\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt; &lt;span class='n'&gt;imageData&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;&lt;/span&gt;&lt;span class='se'&gt;\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='nl'&gt;appendData:&lt;/span&gt;&lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;NSString&lt;/span&gt; &lt;span class='nl'&gt;stringWithFormat:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;--%@--&lt;/span&gt;&lt;span class='se'&gt;\r\n&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;boundary&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; 
  &lt;span class='nl'&gt;dataUsingEncoding:&lt;/span&gt;&lt;span class='n'&gt;NSUTF8StringEncoding&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='nl'&gt;setHTTPBody:&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt; &lt;span class='n'&gt;sendDidStart&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='c1'&gt;// Start the request&lt;/span&gt;
&lt;span class='n'&gt;OAAsynchronousDataFetcher&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;fetcher&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;OAAsynchronousDataFetcher&lt;/span&gt; 
&lt;span class='nl'&gt;asynchronousFetcherWithRequest:&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt;
&lt;span class='nl'&gt;delegate:&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;
&lt;span class='nl'&gt;didFinishSelector:&lt;/span&gt;&lt;span class='k'&gt;@selector&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nl'&gt;sendImage:didFinishWithData:&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='nl'&gt;didFailSelector:&lt;/span&gt;&lt;span class='k'&gt;@selector&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nl'&gt;sendImage:didFailWithError:&lt;/span&gt;&lt;span class='p'&gt;)];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;fetcher&lt;/span&gt; &lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;

&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;oRequest&lt;/span&gt; &lt;span class='n'&gt;release&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/827294' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;As you can see most of the work goes into setting up the authentication headers for the request, as well as filling in the elements of the request body. There are APIs like &lt;a href='http://allseeing-i.com/ASIHTTPRequest'&gt;ASIHTTPRequest&lt;/a&gt;, which handle this for you, however ShareKit doesn&amp;#8217;t use them and I didn&amp;#8217;t want to introduce a 3rd party library. If you take a look at &lt;a href='https://github.com/Gurpartap/GSTwitPicEngine'&gt;Gurpartap's TwitPic engine&lt;/a&gt;, you can see how easy and simple the code would be.&lt;/p&gt;

&lt;p&gt;Overall it&amp;#8217;s a breeze to develop with &lt;a href='http://getsharekit.com'&gt;SharKit&lt;/a&gt; and I&amp;#8217;m glad I digged in deeper. For our next project we&amp;#8217;ll definitely use it and you should at least take a look at it before rolling your own implementation.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>UI Test Automation with Instruments</title>
   <link href="http://dlinsin.github.com/2011/01/31/ui-test-automation.html"/>
   <updated>2011-01-31T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/01/31/ui-test-automation</id>
   <content type="html">&lt;p&gt;One of the most impressive talks for me at &lt;a href='http://dlinsin.blogspot.com/2010/06/wwdc10.html'&gt;WWDC 2010&lt;/a&gt; was session 306 - &amp;#8220;Automating Use Interface Testing with Instruments&amp;#8221;. I&amp;#8217;ve been wanting to check it out ever since iOS 4 was released. A couple of weeks ago, I finally had a chance to give it a test ride with &lt;a href='http://mobile.synyx.de/2010/09/i-think-i-spider-1-0-released/'&gt;&quot;I think I spider&quot;&lt;/a&gt;, one of the Apps I developed.&lt;/p&gt;

&lt;p&gt;All you need to get started is an App, Instruments and some basic JavaScript skills. Apple provides a set of &lt;a href='http://developer.apple.com/library/ios/#documentation/ToolsLanguages/Reference/UIATargetClassReference/UIATargetClass/UIATargetClass.html'&gt;JavaScript libraries&lt;/a&gt;, that you can use to drive your tests and simulate user interaction. Your custom test scripts are run using the Automation Instrument in Apple&amp;#8217;s Instruments App, targeting your App either in the Simulator or on an actual device.&lt;/p&gt;

&lt;p&gt;You can test almost every aspect of user interaction, using Apple&amp;#8217;s JavaScript library. No matter if you want to test shaking, device orientation or the basics like tapping and swiping, you can do all that using basic JavaScript function calls. Apple&amp;#8217;s &lt;a href='https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Built-InInstruments/Built-InInstruments.html%23//apple_ref/doc/uid/TP40004652-CH6-SW75'&gt;documentation&lt;/a&gt; is quite solid, as most of them are, and explains the process in detail.&lt;/p&gt;

&lt;p&gt;For &amp;#8220;I think I spider&amp;#8221; I covered the basic use cases in terms of UI, to make sure it still works after adding new features. Here is a basic example of the JavaScript involved to test &amp;#8220;opening&amp;#8221; the book, after starting the App:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='javascript'&gt;&lt;span class='c1'&gt;// setup&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;target&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;UIATarget&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;localTarget&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;appWindow&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;target&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;frontMostApp&lt;/span&gt;&lt;span class='p'&gt;().&lt;/span&gt;&lt;span class='nx'&gt;mainWindow&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;element&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;target&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

&lt;span class='c1'&gt;// first test&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;testName&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Start Screen Test&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='nx'&gt;UIALogger&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;logStart&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;testName&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='nx'&gt;UIALogger&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;logMessage&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Tapping start screen&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='nx'&gt;appWindow&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;elements&lt;/span&gt;&lt;span class='p'&gt;()[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;start_screen&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;].&lt;/span&gt;&lt;span class='nx'&gt;tap&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt; 

&lt;span class='c1'&gt;// open the book&lt;/span&gt;
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;appWindow&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;elements&lt;/span&gt;&lt;span class='p'&gt;()[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;main_screen&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;].&lt;/span&gt;&lt;span class='nx'&gt;isValid&lt;/span&gt;&lt;span class='p'&gt;())&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='nx'&gt;UIALogger&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;logFail&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;testName&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='nx'&gt;UIALogger&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;logPass&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;testName&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/803902' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;You can see that the JavaScript API is quite easy to use and yet very powerful! After setting this up in the Automation Instrument and running it, you can see the Simulator firing up and tapping the &lt;em&gt;UIImageView&lt;/em&gt; with the accessibility label &amp;#8220;startscreen&amp;#8221; after it became available. It then tests, if the main screen of the App was loaded and either passes or fails the test.&lt;/p&gt;

&lt;p&gt;In order to make our App testable, I had to set the accessibility labels on the elements we wanted to reference from the script. That was the only change I had to make in our code. Since you should take accessibility into consideration anyways, it was a reasonable effort.&lt;/p&gt;

&lt;p&gt;Apple did an awesome job giving us developers the ability to catch regressions and make our life easier. However, there is room for improvement, which has been nicely &lt;a href='http://blog.airsource.co.uk/index.php/2010/08/13/ui-automation-on-the-iphone/'&gt;summarized&lt;/a&gt; by &lt;a href='http://www.airsource.co.uk'&gt;Air Source&lt;/a&gt;. For us, a missing &lt;em&gt;UIALogger.warn&lt;/em&gt; function in the JavaScript library was the biggest downside. Sometimes it&amp;#8217;s okay for a test to fail under certain conditions, but you still want to get a warning about it. I use &lt;em&gt;UIALogger.logMessage&lt;/em&gt; for those cases as a workaround, but it&amp;#8217;s quite easy to miss those lines, since they don&amp;#8217;t stand out.&lt;/p&gt;

&lt;p&gt;Overall, I think it&amp;#8217;s a huge improvement to have a UI testing tool for iOS Apps at hand. There is room for improvement, but the current state of UI Test Automation is already priceless!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>5 Star Rating</title>
   <link href="http://dlinsin.github.com/2011/01/10/five-star-rating.html"/>
   <updated>2011-01-10T00:00:00-08:00</updated>
   <id>http://dlinsin.github.com/2011/01/10/five-star-rating</id>
   <content type="html">&lt;p&gt;A &lt;a href='http://dlinsin.blogspot.com/2010/09/i-think-i-spider.html'&gt;couple of months ago&lt;/a&gt; we release our first own App &amp;#8221;&lt;a href='http://mobile.synyx.de/2010/09/i-think-i-spider-1-0-released/'&gt;I think I spider&lt;/a&gt;&amp;#8221; at Synyx. It features German quotes and sayings directly translated to English. It doesn&amp;#8217;t make much sense to a none-native German speaker, but believe me it&amp;#8217;s hilarious for us.&lt;/p&gt;

&lt;p&gt;The App let&amp;#8217;s you rate those quotes with a 5 star rating, which is directly incorporated into a ranking. Up until today the component in charge of the ranking is a simple bunch of &lt;em&gt;UIImageViews&lt;/em&gt; wired up with Interface Builder and set appropriately when tapped. That means if you want to give a 3 star rating, tapping on the 3rd &lt;em&gt;UIImageView&lt;/em&gt; would fill up the 2 previous one as well. Same goes for changing your mind and going from a 5 to 3 star rating. The logic would unhighlight the 4th and 5th star.&lt;/p&gt;

&lt;p&gt;Now, this works great and it certainly looks beautiful, but have you ever rated an App in the App Store on your iOS device? This is how it looks like:&lt;/p&gt;
&lt;object height='385' width='480'&gt;&lt;param name='movie' value='http://www.youtube.com/v/cbOll4SWwmU?fs=1&amp;amp;hl=en_US' /&gt;&lt;param name='allowFullScreen' value='true' /&gt;&lt;param name='allowscriptaccess' value='always' /&gt;&lt;embed src='http://www.youtube.com/v/cbOll4SWwmU?fs=1&amp;amp;hl=en_US' allowfullscreen='true' type='application/x-shockwave-flash' allowscriptaccess='always' height='385' width='480' /&gt;&lt;/object&gt;
&lt;p&gt;Apple did a great job of just getting everything right with this small little control. The way you can slide your finger over it and the stars light up is just great. Also notice that if you want to reset the rating and go down to 0 stars, you need to swipe your finger all the way to the left. Note, that you can also touch slightly below the star, in order to see the stars above your fingers.&lt;/p&gt;

&lt;p&gt;All those little details were the requirements for the next version of the rating feature of &lt;a href='http://itunes.apple.com/de/app/i-think-i-spider/id390639989?mt=8'&gt;I think I spider&lt;/a&gt;. However, having some spare time over the holidays, I though I&amp;#8217;d write a little component, which does all of that and more: &lt;strong&gt;DLStarRating&lt;/strong&gt;. You can find the code on &lt;a href='https://github.com/dlinsin/DLStarRating'&gt;github&lt;/a&gt;, along with a sample project of how to use the stuff in your next App.&lt;/p&gt;
&lt;object height='385' width='480'&gt;&lt;param name='movie' value='http://www.youtube.com/v/0fpeBo2H7Tc?fs=1&amp;amp;hl=en_US' /&gt;&lt;param name='allowFullScreen' value='true' /&gt;&lt;param name='allowscriptaccess' value='always' /&gt;&lt;embed src='http://www.youtube.com/v/0fpeBo2H7Tc?fs=1&amp;amp;hl=en_US' allowfullscreen='true' type='application/x-shockwave-flash' allowscriptaccess='always' height='385' width='480' /&gt;&lt;/object&gt;
&lt;p&gt;&lt;em&gt;DLStarRating&lt;/em&gt; consists of a configurable number of custom &lt;em&gt;UIButtons&lt;/em&gt; called &lt;em&gt;DLStarView&lt;/em&gt;. They have a different background image for their normal and highlighted state. Those buttons are wrapped in a &lt;em&gt;UIControl&lt;/em&gt; called &lt;em&gt;DLStarRatingControl&lt;/em&gt;, which does all the touch handling. The buttons are centered in the &lt;em&gt;DLStarRatingControl&lt;/em&gt; so keep that in mind when configuring its size.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s quite easy to use &lt;em&gt;DLStarRating&lt;/em&gt; in your code. You can wire it up in Interface Builder (although you won&amp;#8217;t be able to configure it from there) or in your &lt;em&gt;UIViewController&lt;/em&gt; subclass:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objectivec'&gt;&lt;span class='n'&gt;DLStarRatingControl&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;customNumberOfStars&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;DLStarRatingControl&lt;/span&gt; &lt;span class='n'&gt;alloc&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nl'&gt;initWithFrame:&lt;/span&gt;&lt;span class='n'&gt;CGRectMake&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;230&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;320&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;230&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nl'&gt;andStars:&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='n'&gt;customNumberOfStars&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;backgroundColor&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;UIColor&lt;/span&gt; &lt;span class='n'&gt;groupTableViewBackgroundColor&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;span class='n'&gt;customNumberOfStars&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;autoresizingMask&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt;  &lt;span class='n'&gt;UIViewAutoresizingFlexibleLeftMargin&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
                                        &lt;span class='n'&gt;UIViewAutoresizingFlexibleWidth&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
                                        &lt;span class='n'&gt;UIViewAutoresizingFlexibleHeight&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
                                        &lt;span class='n'&gt;UIViewAutoresizingFlexibleRightMargin&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
                                        &lt;span class='n'&gt;UIViewAutoresizingFlexibleTopMargin&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
                                        &lt;span class='n'&gt;UIViewAutoresizingFlexibleBottomMargin&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='n'&gt;customNumberOfStars&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;rating&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;view&lt;/span&gt; &lt;span class='nl'&gt;addSubview:&lt;/span&gt;&lt;span class='n'&gt;customNumberOfStars&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;a href='https://gist.github.com/772510' class='gist'&gt;gist&lt;/a&gt;
&lt;p&gt;To customize the stars, you can replace &lt;em&gt;star.png&lt;/em&gt; and &lt;em&gt;star_highlighted.png&lt;/em&gt; in the images folder under &lt;em&gt;DLStarRating&lt;/em&gt; with your own. The only requirement is that the two images must have the same size.&lt;/p&gt;

&lt;p&gt;If you discover any bugs or have a great idea you want implemented, open an issue on &lt;a href='https://github.com/dlinsin/DLStarRating/issues'&gt;github&lt;/a&gt; or fork the project and help me out!&lt;/p&gt;</content>
 </entry>
 
 
</feed>
