<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Aleksandar • Vacić]]></title>
  <link href="http://aplus.rs/atom.xml" rel="self"/>
  <link href="http://aplus.rs/"/>
  <updated>2013-06-16T21:28:53+02:00</updated>
  <id>http://aplus.rs/</id>
  <author>
    <name><![CDATA[Aleksandar Vacić]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[iOS 7]]></title>
    <link href="http://aplus.rs/2013/ios-7/"/>
    <updated>2013-06-12T11:26:00+02:00</updated>
    <id>http://aplus.rs/2013/ios-7</id>
    <content type="html"><![CDATA[<p>WWDC 2013 keynote was two days ago and I&#8217;m still struggling to come to terms with the changes introduced to my beloved mobile OS and, for over a year now, the field where I make my living.</p>

<p>On one hand, I&#8217;m extremely impressed with the stuff Apple introduced. There are very important and good API changes that are introduced, things that would help me and fellow developers make much better apps.</p>

<p>On the other hand…<em>visual</em> changes are…appalling, simply shockingly bad. This, from a company universally hailed as masters of making things that create emotional connection. Starting from lock screen, over the app icons and to the way UI controls are done, it&#8217;s heartbreaking.</p>

<!-- more -->


<p>When I think about user experience, I see it consisting of three important parts:</p>

<ol>
<li>how it works</li>
<li>how it feels</li>
<li>how it looks</li>
</ol>


<p>This is not accidental ordering. From 1 to 3, it defines the weighted importance of long-term success of any human interface. It&#8217;s most important that it works well, that has a good basis to build on, so it can be slowly and iteratively perfected over time. It&#8217;s important that it feels natural and delights people over time while they discover how it behaves like a natural extensions of their actions and reactions. It&#8217;s important that it looks good, because we, humans, responds most positively to pretty things, with just the right amount of polish.</p>

<p>In that previous paragraph, lies the major issue with iOS 7 as it exists today. We, as humans, judge things in inverted order - from 3 to 1. We must like what we see at the first split-second, otherwise we tend to disregard the thing. And thus fail to discover the inner beauty.</p>

<p><strong>I feel like Apple spent 99% of the time on the important metrics that will define the next decade of iOS, on works/feels parts. And 1% on the looks part.</strong></p>

<p>I&#8217;m probably wrong, but that&#8217;s how it feels to me.
From all that I saw in the WWDC videos (under NDA, so can&#8217;t really tell much) they wonderfully succeeded with 1/2. The API changes and new stuff that are introduced are great, building on amazing stuff done in iOS 6 (collection views, auto layout etc). The dev tools are improved and fixed in ways that took away the most troubling parts of the everyday development life.</p>

<p>The beauty and the feel of the animations and transitions more than once made me to jump with joy. I smiled like a kid in a candy store every time a transition happened from starting/closing an app, inter-app navigation, inner-app navigation between views etc. It&#8217;s really, really well done.</p>

<p>But those are all fleeting moments. The majority of time, I, as customer, am looking at these poor app icons:</p>

<p><img src="http://aplus.rs/images/2013/ios7-appicons.png" alt="" /></p>

<p>And these wireframe-ish in-app icons (will 3rd-party service&#8217;s icons be auto-processed into this?):</p>

<p><img src="http://aplus.rs/images/2013/ios7-share.png" alt="" /></p>

<p>And this terribly illegible UI:</p>

<p><img src="http://aplus.rs/images/2013/ios7-cc.png" alt="" />
<img src="http://aplus.rs/images/2013/ios7-tabbar.png" alt="" /></p>

<p>And this inconsistently applied HIG direction:</p>

<p><img src="http://aplus.rs/images/2013/ios7-contacts.png" alt="" /></p>

<p>And these garish line icons that poke me in the eye all while claiming they are done this way so they emphasize the content:</p>

<p><img src="http://aplus.rs/images/2013/ios7-eyepoke.png" alt="" />
<img src="http://aplus.rs/images/2013/ios7-eyepoke2.png" alt="" /></p>

<p>At first, I thought these are temporary stuff, part of beta 1. After all, it may look horrible but it&#8217;s important that developers get their hands on iOS 7 so they can prepare their apps. But then I realized that this is used in promotional videos on apple.com. This is used and details are specified in iOS 7 HIG. That they actually changed app icon&#8217;s corner radius and size (for the worse) which is not something you waste your time on is this is only temporary.</p>

<p>I now think this is here to stay for years to come, which is making me really sad.</p>

<p>Did it have to be this way? Absolutely not and few good souls used couple of hours or a day and showed what you could do with just a little more care.</p>

<p><a href="http://dribbble.com/shots/1109343-iOS-7-Redesign"><img src="http://aplus.rs/images/2013/ios7-dribble-home.jpg" alt="Home screen" /></a>
<a href="http://dribbble.com/shots/1109500-iOS-7"><img src="http://aplus.rs/images/2013/ios7-dribble-maps.png" alt="Maps" /></a></p>

<p>For goodness sake, just look at the maps example and tell me which one of the toolbar/navbar feels more natural. The app icon grid is beyond commenting - example on the left is more consistent, better looking and with perfect corner radius for the icons.</p>

<p>Apple set fire on the last 6 years of iterations and started from new. They could have taken a bit more time and start from a much better position than this 3-yo children&#8217;s scribble book.
Whoever pushed for and decided this is the proper way to go is not fit for the job. Apple has managed to move from the best looking mobile OS on the market to worst looking one, by a whole mile. <br>
This is the current state of the market:</p>

<p><img src="http://aplus.rs/images/2013/mobile-os-comparison.jpg" alt="iOS 6, Windows Phone 8, HTC Sense 5, Samsung TouchWiz, iOS 7" /></p>

<p>Now you tell me, honestly - if you knew nothing of the market and you are a feature phone customer going to get a new phone in the store - which one of the above would you choose? <br>
Honestly?</p>

<p>For more perspective, agreeing and disagreeing with me, read these:</p>

<ul>
<li><a href="http://www.macstories.net/stories/ios-7-thoughts-and-questions/">MacStories</a>, by Federico Viticci</li>
<li><a href="http://furbo.org/2013/06/11/been-there-done-that/">Craig Hockenberry</a></li>
<li><a href="http://frankchimero.com/blog/2013/06/generosity-of-perspective/">Frank Chimero</a></li>
<li><a href="http://512pixels.net/2013/06/rolling-on/">Stephen Hackett</a></li>
<li><a href="http://daringfireball.net/2013/06/ios_7_signature">John Gruber</a></li>
<li><a href="https://medium.com/product-experience/9a7b4648fe8b">Mike Rundle</a></li>
<li><a href="https://medium.com/wwdc-round-up/275a56688510">Ryan Katkov</a></li>
<li><a href="http://thisisentropy.com/chatterbox/2013/6/12/start-preparing-for-ios-7-now">Entropy</a></li>
<li><a href="http://blog.jaredsinclair.com/post/52888572915/apps-are-content-too-there-is-a-word-that">Jared Sinclair</a></li>
<li><a href="http://releasecandidateone.com/253:given_time">Chris Clark</a></li>
<li><a href="http://ianstormtaylor.com/whats-wrong-with-the-ios-7-icons/">Ian Storm Taylor</a></li>
<li><a href="http://www.imore.com/ios-7-and-continuing-gamification-interface">iMore</a> by Rene Ritchie</li>
</ul>


<p>Even people that are defending the iOS 7 visual changes, people that say this is how Apple rolls, compare it to OS X and iMac reboots - no one, and I mean no one is saying that they love the new looks. Can you remember a successful Apple product where even their most hardened supporters felt like that..?</p>

<p><strong>Update</strong> (late evening of Jun 12):
Matthew Panzarino just posted <a href="http://thenextweb.com/apple/2013/06/12/why-does-the-design-of-ios-7-look-so-different/">an amazing article</a> at The Next Web, with several details that finally make sense in this whole mess:</p>

<ul>
<li>previous Apple UI team had no say about the iOS 7 UI guidelines</li>
<li>those were done by marketing/print people <del>and possibly even former Color team</del></li>
</ul>


<p>I&#8217;m lost for words. Jiminy!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RTFlyoutMenu - drop-down menu component for iOS]]></title>
    <link href="http://aplus.rs/2013/rtflyoutmenu-drop-down-menu-component-for-ios/"/>
    <updated>2013-05-13T12:21:00+02:00</updated>
    <id>http://aplus.rs/2013/rtflyoutmenu-drop-down-menu-component-for-ios</id>
    <content type="html"><![CDATA[<p>I&#8217;ve long had a fascination with fly-out or drop-down menus. One of my most successful web components was <a href="http://aplus.rs/adxmenu/">ADxMenu</a> which I continually developed for years, as things and technologies evolved in web space.</p>

<p>On iOS though, screens were smaller in the beginning and different UI concepts were dominant thus I mostly forgot about this. Until recently, when I had the need to implement a multi-part filtering component for an iPad app I was creating.</p>

<p><img src="http://aplus.rs/images/2013/rtflyoutmenu.png" alt="" /></p>

<p>So, <a href="https://github.com/radianttap/RTFlyoutMenu">RTFlyoutMenu</a> was born.<!-- more --></p>

<h2>How it works</h2>

<p>Basic idea is this:</p>

<ul>
<li>Show a list of main items, which are filter categories.</li>
<li>When user taps any of them, show a list of sub items (filter options).</li>
<li>When sub-item is tapped, replace main item with it and close the submenu.</li>
<li>Main item is shown at the bottom of the submenu, so you can reset back to default.</li>
</ul>


<p>Thus better name is maybe RTFilterMenu, but I started with fly-out and left it as such. How it works in the end depends a lot on how you implement delegate methods, so it can be both filter and/or a menu.</p>

<p>What I needed for this particular instance is to quickly filter a very large catalog. In practice, this works extremely well to narrow down to just items of particular materials, colors, seasons etc.</p>

<h2>Implementation</h2>

<p>I modeled it per UITableView and its friends. So you have <code>RTFlyoutMenuDataSource</code> and <code>RTFlyoutMenuDelegate</code>.</p>

<p>Data source is self-explanatory. You define main-level items and then sub-menu items for each of them.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@protocol</span> <span class="nc">RTFlyoutMenuDataSource</span> <span class="o">&lt;</span><span class="n">NSObject</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">-</span> <span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="nl">numberOfMainItemsInFlyoutMenu:</span><span class="p">(</span><span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="p">)</span><span class="n">flyoutMenu</span><span class="p">;</span>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nf">flyoutMenu:</span><span class="p">(</span><span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="p">)</span><span class="nv">flyoutMenu</span> <span class="nf">titleForMainItem:</span><span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="nv">mainItemIndex</span><span class="p">;</span>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="nf">flyoutMenu:</span><span class="p">(</span><span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="p">)</span><span class="nv">flyoutMenu</span> <span class="nf">numberOfItemsInSubmenu:</span><span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="nv">mainItemIndex</span><span class="p">;</span>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nf">flyoutMenu:</span><span class="p">(</span><span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="p">)</span><span class="nv">flyoutMenu</span> <span class="nf">titleForSubItem:</span><span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="nv">subItemIndex</span> <span class="nf">inMainItem:</span><span class="p">(</span><span class="n">NSUInteger</span><span class="p">)</span><span class="nv">mainItemIndex</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Delegate methods tell you what user has tapped and thus you can respond to those changes.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@protocol</span> <span class="nc">RTFlyoutMenuDelegate</span> <span class="o">&lt;</span><span class="n">NSObject</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="k">@optional</span>
</span><span class='line'><span class="o">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nl">flyoutMenu:</span><span class="p">(</span><span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="p">)</span><span class="n">flyoutMenu</span> <span class="nl">didSelectMainItemWithIndex:</span><span class="p">(</span><span class="n">NSInteger</span><span class="p">)</span><span class="n">index</span><span class="p">;</span>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">flyoutMenu:</span><span class="p">(</span><span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="p">)</span><span class="nv">flyoutMenu</span> <span class="nf">didSelectSubItemWithIndex:</span><span class="p">(</span><span class="n">NSInteger</span><span class="p">)</span><span class="nv">subIndex</span> <span class="nf">mainMenuItemIndex:</span><span class="p">(</span><span class="n">NSInteger</span><span class="p">)</span><span class="nv">mainIndex</span><span class="p">;</span>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">didReloadFlyoutMenu:</span><span class="p">(</span><span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="p">)</span><span class="nv">flyoutMenu</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Initial setup</h3>

<p>RTFlyoutMenu is UIView and thus you can place it anywhere you want and it will automatically try to center itself in it. By default, I place in a container view. <em>You must have the container and pass it as canvasView to the menu itself.</em> Here&#8217;s a crude setup from the demo app:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">viewDidAppear:</span><span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nv">animated</span> <span class="p">{</span>
</span><span class='line'>  <span class="p">[</span><span class="n">super</span> <span class="nl">viewDidAppear:</span><span class="n">animated</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">NSDictionary</span> <span class="o">*</span><span class="n">options</span> <span class="o">=</span> <span class="err">@</span><span class="p">{</span>
</span><span class='line'>      <span class="nl">RTFlyoutMenuUIOptionInnerItemSize:</span> <span class="p">[</span><span class="n">NSValue</span> <span class="nl">valueWithCGSize:</span><span class="n">CGSizeMake</span><span class="p">(</span><span class="mi">22</span><span class="p">,</span> <span class="mi">22</span><span class="p">)],</span>
</span><span class='line'>      <span class="nl">RTFlyoutMenuUIOptionSubItemPaddings:</span> <span class="p">[</span><span class="n">NSValue</span> <span class="nl">valueWithUIEdgeInsets:</span><span class="n">UIEdgeInsetsMake</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">15</span><span class="p">)]</span>
</span><span class='line'>  <span class="p">};</span>
</span><span class='line'>  <span class="n">RTFlyoutMenu</span> <span class="o">*</span><span class="n">m</span> <span class="o">=</span> <span class="p">[[</span><span class="n">RTFlyoutMenu</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithDelegate:</span><span class="n">self</span> <span class="nl">dataSource:</span><span class="n">self</span> <span class="nl">position:</span><span class="n">kRTFlyoutMenuPositionTop</span> <span class="nl">options:</span><span class="n">options</span><span class="p">];</span>
</span><span class='line'>  <span class="n">m</span><span class="p">.</span><span class="n">canvasView</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">view</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">CGRect</span> <span class="n">mf</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">frame</span><span class="p">;</span>
</span><span class='line'>  <span class="n">CGRect</span> <span class="n">cf</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">menuContainerView</span><span class="p">.</span><span class="n">bounds</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// center menu in container view</span>
</span><span class='line'>  <span class="n">CGFloat</span> <span class="n">newOriginX</span> <span class="o">=</span> <span class="p">(</span><span class="n">cf</span><span class="p">.</span><span class="n">size</span><span class="p">.</span><span class="n">width</span> <span class="o">-</span> <span class="n">mf</span><span class="p">.</span><span class="n">size</span><span class="p">.</span><span class="n">width</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
</span><span class='line'>  <span class="n">CGFloat</span> <span class="n">newOriginY</span> <span class="o">=</span> <span class="p">(</span><span class="n">cf</span><span class="p">.</span><span class="n">size</span><span class="p">.</span><span class="n">height</span> <span class="o">-</span> <span class="n">mf</span><span class="p">.</span><span class="n">size</span><span class="p">.</span><span class="n">height</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">newOriginX</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">mf</span><span class="p">.</span><span class="n">origin</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">newOriginX</span><span class="p">;</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">newOriginY</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">mf</span><span class="p">.</span><span class="n">origin</span><span class="p">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">newOriginY</span><span class="p">;</span>
</span><span class='line'>  <span class="n">m</span><span class="p">.</span><span class="n">frame</span> <span class="o">=</span> <span class="n">mf</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//   m.backgroundColor = [UIColor redColor];</span>
</span><span class='line'>  <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">menuContainerView</span> <span class="nl">addSubview:</span><span class="n">m</span><span class="p">];</span>
</span><span class='line'>  <span class="n">self</span><span class="p">.</span><span class="n">flyoutMenu</span> <span class="o">=</span> <span class="n">m</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// look &amp; feel</span>
</span><span class='line'>  <span class="p">[[</span><span class="n">RTFlyoutItem</span> <span class="nl">appearanceWhenContainedIn:</span><span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">menuContainerView</span> <span class="n">class</span><span class="p">],</span> <span class="nb">nil</span><span class="p">]</span> <span class="nl">setTitleColor:</span><span class="p">[</span><span class="n">UIColor</span> <span class="n">darkGrayColor</span><span class="p">]</span> <span class="nl">forState:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
</span><span class='line'>  <span class="p">[[</span><span class="n">RTFlyoutItem</span> <span class="nl">appearanceWhenContainedIn:</span><span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">menuContainerView</span> <span class="n">class</span><span class="p">],</span> <span class="nb">nil</span><span class="p">]</span> <span class="nl">setTitleShadowColor:</span><span class="p">[</span><span class="n">UIColor</span> <span class="n">whiteColor</span><span class="p">]</span> <span class="nl">forState:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>For the full set of options you can pass, take a look at the <a href="https://github.com/radianttap/RTFlyoutMenu/blob/master/RTFlyoutMenu/RTFlyoutMenu.h">header file</a>.</p>

<h2>Improvements</h2>

<p>There&#8217;s room for a lot more customization options (like colors, fonts etc), but this is what I needed for this particular project.</p>

<p>As it is, component will lightly try to fit whatever content you give it. So if your submenu has over 10 items, it will break them into columns. This is as far it goes though and will not check if all columns can fit.</p>

<p>On interface rotation it will recenter main menu, but any open submenus will remain where they were, which is not optimal. Again, in my particular use-case this was not an issue (all submenus were more or less the same size and placement) so I did not work on it.</p>

<p>And so on and on. There is always room for improvement, so fork away. :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Never save absolute file paths in your iOS app]]></title>
    <link href="http://aplus.rs/2013/never-save-absolute-file-paths-in-your-ios-app/"/>
    <updated>2013-04-28T13:03:00+02:00</updated>
    <id>http://aplus.rs/2013/never-save-absolute-file-paths-in-your-ios-app</id>
    <content type="html"><![CDATA[<p>There&#8217;s a mistake I make every 6 months or so and I hope writing  a blog post about it will finally engrave it into the back of my mind.</p>

<p>Have you seen how the file paths look like for the files in your iOS app&#8217;s little sandbox? Something like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>/var/mobile/Applications/F71BA910-A1F0-4B39-85CB-775806ACFF62/Documents/orders/1832006/1.pdf
</span></code></pre></td></tr></table></div></figure>


<p>The mistake I make is that I take this full URL and then save it into to Core Data storage or wherever (in this case, as order file path). And this will work if you never make updates to the app. However, if you do publish an update to the app, this URL will not be valid anymore.</p>

<p>The gibberish bit in the middle - <code>F71BA910-A1F0-4B39-85CB-775806ACFF62</code> - is path that is specific to a given app <em>version</em>. So, when you update, your new app version will get some other string in there and all your previously saved / hard-coded URLs will be useless.</p>

<p>What you need to save is only the part that you control and maintain - in my case that&#8217;s <code>orders/1832006/1.pdf</code>. <em>Which excludes the <code>Documents</code> part as well</em> as this is automatically created by iOS for your app. <code>Documents</code> is one of several app directories that you can and <em>should</em> fetch using the provided iOS APIs. There is nothing that guaranties that in some future iOS versions Apple won&#8217;t rename Documents to something else, so you should not think it&#8217;s there to stay.</p>

<p>So, what&#8217;s the proper way to read/save local path files?</p>

<!-- more -->


<p>Apple already provides few useful functions:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="c1">//   get absolute path for your app</span>
</span><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="n">NSHomeDirectory</span><span class="p">()</span>
</span><span class='line'><span class="c1">//   get absolute path for your app&#39;s temporary (tmp) folder</span>
</span><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="n">NSTemporaryDirectory</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>Along with this, I&#8217;ve long been using a helper <code>NSFileManager</code> methods that <a href="http://ericasadun.com">Erica Sadun</a> wrote way back in iPhone OS 3.0 time, for her iPhone Developer Cookbook. I have updated it over time and the current version that I use is in my <a href="https://github.com/radianttap/NSFileManager-Utilities">Github repository</a>.
In it, you will find more appropriately named methods:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="c1">//   this gives you an absolute path to YOUR_APP/Documents directory</span>
</span><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="nf">NSDocumentsFolder</span><span class="p">();</span>
</span><span class='line'><span class="c1">//   this gives you an absolute path to YOUR_APP/Library directory</span>
</span><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="nf">NSLibraryFolder</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>


<p>Using <em>Folder</em> in the names instead of <em>Directory</em> is deliberate, to avoid potential App Store rejections due to use of private methods that Apple may be/is using.</p>

<p>This small extension also have few more very useful methods:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">+</span> <span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nf">findOrCreateDirectoryPath:</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nv">path</span><span class="p">;</span>
</span><span class='line'><span class="k">+</span> <span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nf">findOrCreateDirectoryPath:</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nv">path</span> <span class="nf">backup:</span><span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nv">shouldBackup</span> <span class="nf">dataProtection:</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nv">dataProtection</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>First one is simply a shortcut for the second with default values. So, what this does is - you supply an absolute folder <code>path</code> and it will return <code>TRUE</code> if it has found it (and it is a directory) or has successfully created it. In any other case, it will return <code>FALSE</code>.</p>

<p>Additionally, if you want to exclude this folder from iCloud/iTunes backups, then send NO for the shouldBackup (default is YES).
Lastly, if you want to use iOS Data Protection APIs, then supply the appropriate protection level constant.
These last two actions are best-effort side-effects - what happens when trying to set them does not influence the method result. This is just the way it worked for me here, you can change this as you want/need.</p>

<p>For example, here&#8217;s a sample folder path function I added for one of the apps I created:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">+</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nf">RTOrdersFolder</span> <span class="p">{</span>
</span><span class='line'>  
</span><span class='line'>  <span class="n">NSString</span> <span class="o">*</span><span class="n">f</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSDocumentsFolder</span><span class="p">()</span> <span class="nl">stringByAppendingPathComponent:</span><span class="s">@&quot;orders&quot;</span><span class="p">];</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">([</span><span class="n">NSFileManager</span> <span class="nl">findOrCreateDirectoryPath:</span><span class="n">f</span> <span class="nl">shouldBackup:</span><span class="n">NO</span> <span class="nl">dataProtection:</span><span class="n">NSFileProtectionComplete</span><span class="p">])</span>
</span><span class='line'>      <span class="k">return</span> <span class="n">f</span><span class="p">;</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">return</span> <span class="nb">nil</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>On first time this is called, it will create this folder inside the Documents folder, mark it so it does not go into iCloud (don&#8217;t ask) and also to fully protect it from prying eyes.
Every subsequent access to this folder will simply return its absolute path.</p>

<p>How do I use this new method in the app? Here&#8217;s typical (simplified) usage (<code>order</code> is custom object in the app):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="n">fullOrderPath</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSFileManager</span> <span class="n">RTOrdersFolder</span><span class="p">]</span> <span class="nl">stringByAppendingPathComponent:</span><span class="n">order</span><span class="p">.</span><span class="n">orderId</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'><span class="n">order</span><span class="p">.</span><span class="n">finalPath</span> <span class="o">=</span> <span class="p">[</span><span class="n">fullOrderPath</span> <span class="nl">stringByReplacingOccurrencesOfString:</span><span class="p">[</span><span class="n">NSFileManager</span> <span class="n">RTOrdersFolder</span><span class="p">]</span> <span class="nl">withString:</span><span class="s">@&quot;&quot;</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>Thus when you persist the order object, only the relevant part of the path - the part that you have control over - is saved. When you need full path again, it&#8217;s easy to recreate it.</p>

<p>I recommend that you create methods like this for any file resources that you often reference in your app.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A single bug in my StoreKit code that lost me 90% of IAP sales]]></title>
    <link href="http://aplus.rs/2012/a-single-bug-in-my-storekit-code-that-lost-me-90-of-iap-sales/"/>
    <updated>2012-08-04T20:01:33+02:00</updated>
    <id>http://aplus.rs/2012/a-single-bug-in-my-storekit-code-that-lost-me-90-of-iap-sales</id>
    <content type="html"><![CDATA[<p>In <a href="http://radianttap.com/banca/">Banca</a>, my very successful currency conversion app for iPhone, I added ability to buy various themes, through in-app purchase. I followed the guide, implemented all the bits and pieces of the whole workflow. Apart from one important part.</p>

<p>My theme store is modal view controller and in its <code>init</code> method I got this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nf">initWithNibName:</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nv">nibNameOrNil</span> <span class="nf">bundle:</span><span class="p">(</span><span class="n">NSBundle</span> <span class="o">*</span><span class="p">)</span><span class="nv">nibBundleOrNil</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">self</span> <span class="o">=</span> <span class="p">[</span><span class="n">super</span> <span class="nl">initWithNibName:</span><span class="n">nibNameOrNil</span> <span class="nl">bundle:</span><span class="n">nibBundleOrNil</span><span class="p">];</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">([</span><span class="n">SKPaymentQueue</span> <span class="n">canMakePayments</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>          <span class="c1">// set observer, to follow transactions processing</span>
</span><span class='line'>          <span class="p">[[</span><span class="n">SKPaymentQueue</span> <span class="n">defaultQueue</span><span class="p">]</span> <span class="nl">addTransactionObserver:</span><span class="n">self</span><span class="p">];</span>
</span><span class='line'>      <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The trouble was, I forgot to add this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">dealloc</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">([</span><span class="n">SKPaymentQueue</span> <span class="n">canMakePayments</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>      <span class="p">[[</span><span class="n">SKPaymentQueue</span> <span class="n">defaultQueue</span><span class="p">]</span> <span class="nl">removeTransactionObserver:</span><span class="n">self</span><span class="p">];</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>




<!-- more -->


<h3>Where it&#8217;s crashing</h3>

<p>This is the symbolicated crash report:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>2 libsystem_c.dylib 0x33e257ec _sigtramp + 48
</span><span class='line'>3 StoreKit 0x32836792 __NotifyObserverAboutChanges + 38
</span><span class='line'>4 CoreFoundation 0x374b6afa CFArrayApplyFunction + 38
</span><span class='line'>5 StoreKit 0x32836762 -<span class="o">[</span>SKPaymentQueue _notifyObserversAboutChanges:<span class="o">]</span> + 118
</span><span class='line'>6 StoreKit 0x32836452 -<span class="o">[</span>SKPaymentQueue _addLocalTransactionForPayment:<span class="o">]</span> + 250
</span><span class='line'>7 StoreKit 0x3283594c -<span class="o">[</span>SKPaymentQueue addPayment:<span class="o">]</span> + 444
</span><span class='line'>8 Banca 0x000f1612 -<span class="o">[</span>ThemeStoreViewController buy:<span class="o">]</span> <span class="o">(</span>ThemeStoreViewController.m:477<span class="o">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>It crashes on that second line, with <code>__NotifyObserverAboutChanges</code>.</p>

<h3>Why it crashes</h3>

<p>If you look at the crash report, it crashes when customer attempts to buy the product. However, I did test it (of course) and have managed to buy a theme with no issues. This is where <a href="http://TestFlightapp.com">TestFlightapp.com</a> checkpoints came in handy. Along with crash log above, I also have the checkpoint events I have sprinkled throughout my code. These are anonymous usage tracking calls, which helps me figure out how are people using my app.</p>

<p>In this case, it also helped me find the bug because - if you have set enough checkpoints - it gives you step-by-step scenario for repeating the issue.</p>

<p>This is the checkpoints list where the bug appears:</p>

<ul>
<li><p>00:00:16 Passed checkpoint: (MAIN_VIEW)</p></li>
<li><p>00:00:18 Passed checkpoint: (APP_STORE_PRODUCTS_GETTING)</p></li>
<li><p>00:00:18 Passed checkpoint: (THEME_STORE)</p></li>
<li><p>00:00:19 Passed checkpoint: (APP_STORE_PRODUCTS_RECEIVED)</p></li>
<li><p>00:00:27 Passed checkpoint: (MAIN_VIEW)</p></li>
<li><p>00:00:31 Passed checkpoint: (THEME_STORE)</p></li>
<li><p>00:00:31 Passed checkpoint: (APP_STORE_PRODUCTS_GETTING)</p></li>
<li><p>00:00:32 Passed checkpoint: (APP_STORE_PRODUCTS_RECEIVED)</p></li>
<li><p>00:00:37 Crashed (Signal)</p></li>
</ul>


<p>As you can see, if you open the store, then close, then open again and then attempt buying, the app crashes. Why?</p>

<p>Well, see the code at the start of the post - I&#8217;m adding my view controller as <code>SKPaymentQueue</code> transaction observer, but I was not removing it (the missing <code>dealloc</code>). So when you do this twice in a row in one session, StoreKit will attempt to deliver payment processing notification to current store VC and to the old one, which is released. Hence the <code>SIGSEGV</code> crash.</p>

<p>When looking at the number of store opening checkpoints versus the completed sales, I estimate I lost about 90% of sales over the last few days that the app is live.</p>

<p>I asked Apple for expedited review of the <a href="http://radianttap.com/banca/">Banca 3.0.1</a>, so hopefully they will do it.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Naming the company]]></title>
    <link href="http://aplus.rs/2012/naming-the-company/"/>
    <updated>2012-07-24T14:33:35+02:00</updated>
    <id>http://aplus.rs/2012/naming-the-company</id>
    <content type="html"><![CDATA[<p>When I was forming a company now known as <a href="http://radianttap.com/">Radiant Tap</a>, I was brain-storming on various name ideas.</p>

<!-- more -->


<p>This is the list I found in old notes:</p>

<ul>
<li><p>Beautiful Vine</p></li>
<li><p>Inspired Vine</p></li>
<li><p>Green Canopy</p></li>
<li><p>Inspired Canopy</p></li>
<li><p>Path by the Vines</p></li>
<li><p>Vines on the Hill</p></li>
<li><p>Grown by Wine</p></li>
<li><p>Vigneron</p></li>
<li><p>Code Burrel</p></li>
<li><p>Code Cask</p></li>
<li><p>Delicate Vine</p></li>
<li><p>Promising Vine</p></li>
<li><p>Flying Canopy</p></li>
<li><p>Made by Wine</p></li>
<li><p>Mobile Canopy</p></li>
<li><p>AppCanopy</p></li>
<li><p>Connected Canopy</p></li>
<li><p>Radiant Flair</p></li>
<li><p>Code Flair</p></li>
<li><p>Sky Canopy</p></li>
<li><p>Air Canopy</p></li>
<li><p>Air Flair</p></li>
<li><p>Shaded by vines</p></li>
<li><p>Canopy Shade</p></li>
<li><p>Hot Canopy</p></li>
<li><p>Noble Canopy</p></li>
<li><p>First Canopy</p></li>
<li><p>Notable Canopy</p></li>
<li><p><em>Radiant Canopy</em></p></li>
<li><p>Path &amp; Canopy</p></li>
<li><p>Secret Path</p></li>
<li><p>Secret Canopy</p></li>
<li><p>Canopy Secret</p></li>
<li><p>Hidden Canopy</p></li>
<li><p>Hidden Path</p></li>
<li><p>Canopy Trail</p></li>
</ul>


<p>As you can see, I was very much into vineyards and wines, so a lot of these were attempts to combine networking and technology with vines. I eventually decided on Radiant Canopy but after only few months became aware it&#8217;s really not working and switched to Radiant Tap.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Tip: revert pngcrush optimization in Xcode 4.3]]></title>
    <link href="http://aplus.rs/2012/tip-revert-pngcrush-optimization-in-xcode-4-3/"/>
    <updated>2012-05-21T22:50:07+02:00</updated>
    <id>http://aplus.rs/2012/tip-revert-pngcrush-optimization-in-xcode-4-3</id>
    <content type="html"><![CDATA[<p>When you are adding PNG images to an iOS app, Xcode will optimize and compress them when compiling, using a tool called <code>pngcrush</code>. To revert this optimization back, copy the <code>.png</code> files from the <code>.ipa</code> bundle into some folder and run this in terminal</p>

<pre><code>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/pngcrush -dir SOME_DIR -revert-iphone-optimizations -q *.png
</code></pre>

<p><code>SOME_DIR</code> is a destination path, something like <code>~/temp</code>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Best Couch to 5k iPhone app on the App Store]]></title>
    <link href="http://aplus.rs/2012/best-couch-to-5k-iphone-app-on-the-app-store/"/>
    <updated>2012-05-17T13:05:59+02:00</updated>
    <id>http://aplus.rs/2012/best-couch-to-5k-iphone-app-on-the-app-store</id>
    <content type="html"><![CDATA[<p>Seriously, it is.</p>

<p><a href="http://radianttap.com/couchto5k/">Go Couch to 5k</a> 2.0 went live last week with much improved speed/distance tracking (way more accurate than before), full <a href="http://dailymile.com">dailymile</a> integration and improved integration with Twitter and Facebook. New version features a female coaching voice along with improved mail voice.</p>

<p>If you are thinking should you start running, go ahead and give this one a spin, it&#8217;s currently <a href="http://itunes.apple.com/us/app/go-couch-to-5k/id406825271?mt=8">$2.99 on the App Store</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to: update project build version automatically, in Xcode 4.3]]></title>
    <link href="http://aplus.rs/2012/how-to-update-project-build-version-automatically-in-xcode-4-3/"/>
    <updated>2012-05-08T18:31:18+02:00</updated>
    <id>http://aplus.rs/2012/how-to-update-project-build-version-automatically-in-xcode-4-3</id>
    <content type="html"><![CDATA[<p>This is very useful if you use service like <a href="http://testflightapp.com/">TestFlight</a> (if you are not, you should) and in general gives you idea how much you worked and tested.</p>

<blockquote><p>Hey look, I did 500+ builds for the new version.
:)</p></blockquote>

<!-- more -->


<p>Anyway, first make sure your project&#8217;s Info.plist has <code>Bundle version</code> (raw key name is <code>CFBuildVersion</code>) set to integer value, <code>0</code> or <code>1</code> or whatever you want as starting value. In Xcode 4.3 this can be set in <em>Summary</em> tab, the <em>Build</em> field, like this:</p>

<p><img src="http://aplus.rs/images/2012/Screen-Shot-2012-05-08-at-16.10.32.png" alt="" /></p>

<p><em>Version</em> is what you will market to end users, what you will respond when setting up an update in iTunes Connect. <em>Build</em> is mostly for developers and testers, as a reference for bug tracking/fixing.</p>

<p>Next, add <code>Run Script</code> phase in the <em>Build Phases</em> for the main target and paste this script:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">buildNumber</span><span class="o">=</span><span class="k">$(</span>/usr/libexec/PlistBuddy -c <span class="s2">&quot;Print CFBundleVersion&quot;</span> <span class="s2">&quot;${PROJECT_DIR}/${INFOPLIST_FILE}&quot;</span><span class="k">)</span>
</span><span class='line'><span class="nv">buildNumber</span><span class="o">=</span><span class="k">$((</span><span class="nv">$buildNumber</span> <span class="o">+</span> <span class="m">1</span><span class="k">))</span>
</span><span class='line'>/usr/libexec/PlistBuddy -c <span class="s2">&quot;Set :CFBundleVersion $buildNumber&quot;</span> <span class="s2">&quot;${PROJECT_DIR}/${INFOPLIST_FILE}&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>It looks like this in Xcode 4.3</p>

<p><img src="http://aplus.rs/images/2012/Screen-Shot-2012-05-08-at-16.11.08.png" alt="" /></p>

<p>Most important thing here is that this <code>Run Script</code> phase must be before <code>Copy bundle resources</code>. If you forget that, your builds will always be one step behind.</p>

<p>In the end, if you want to show this in your app, this is one way to do it:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">[</span><span class="n">NSString</span> <span class="nl">stringWithFormat:</span><span class="s">@&quot;%@ (%@)&quot;</span><span class="p">,</span>
</span><span class='line'> <span class="p">[[</span><span class="n">NSBundle</span> <span class="n">mainBundle</span><span class="p">]</span> <span class="nl">objectForInfoDictionaryKey:</span><span class="s">@&quot;CFBundleShortVersionString&quot;</span><span class="p">],</span>
</span><span class='line'> <span class="p">[[</span><span class="n">NSBundle</span> <span class="n">mainBundle</span><span class="p">]</span> <span class="nl">objectForInfoDictionaryKey:</span><span class="s">@&quot;CFBundleVersion&quot;</span><span class="p">]</span>
</span><span class='line'><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Re-charging dead Macbook pro battery after a long discharge]]></title>
    <link href="http://aplus.rs/2012/re-charging-dead-macbook-pro-battery-after-a-long-discharge/"/>
    <updated>2012-03-23T13:35:11+01:00</updated>
    <id>http://aplus.rs/2012/re-charging-dead-macbook-pro-battery-after-a-long-discharge</id>
    <content type="html"><![CDATA[<p>Recently my family went away from home for two months. While preparing to go, we left my wife&#8217;s Macbook Pro at home and got a bit of a nasty surprise when we returned. The Macbook pro wouldn&#8217;t start at all unless plugged-in. And then it showed that battery was not charging and its charge capacity is 0 (you can see this in System Information app). And the green indicator on the MagSafe adapter never went to orange (charging light), even after we left it overnight.</p>

<p>I then recalled similar account by <a href="http://hivelogic.com/">Dan Benjamin</a> - he also left a Macbook untouched for several weeks. The battery discharged so much that it was impossible to kick-start the charging again. He eventually had the battery replaced with new.</p>

<!-- more -->


<p>The recommendation is that, when you know a device will not be used for prolonged period of time, to remove the battery out (and that charge capacity should be about 40% at that point). In newer Mac portables though, battery is not removable (at least not without opening the case). Thus I assumed that this must be something Apple has thought about. A quick search offered a possible solution:</p>

<p><strong>Unplug the device and all the peripherals.</strong></p>

<p><strong>Hold Ctrl + Option + Shift <em>and</em> Power button for 5-6s, then release them all.</strong></p>

<p>Plugging back in, I was relieved to see the orange light. At first, it showed that charging would take 10h :) but after 5mins or so it got down to normal 1.5h-ish.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Review: WaterField Ultimate SleeveCase for iPad]]></title>
    <link href="http://aplus.rs/2011/review-waterfield-ultimate-sleevecase-for-ipad/"/>
    <updated>2011-11-17T12:24:57+01:00</updated>
    <id>http://aplus.rs/2011/review-waterfield-ultimate-sleevecase-for-ipad</id>
    <content type="html"><![CDATA[<p>I&#8217;ve long been hearing about <a href="http://sfbags.com/">WaterField</a>, from the blogs I follow. Two main impressions crystallized over time: good products and good customer support. So when I was getting the iPad brought over from the US, I took the opportunity to order their sleeve case.</p>

<p>I prefer the sleeve case to larger bags. I want my gadgets to be fittingly protected when carried and I&#8217;ll then buy a larger bag and just throw each in.</p>

<!-- more -->


<p>I use Incase sleeve cases for my laptops and in fact wanted to get their sleeve for the iPad too, but was unable to order because they insist on US-based billing address for the card. In this age, that&#8217;s rather stupid and it&#8217;s hurting their business, but such as life, they sure have their reasons.</p>

<p><img src="http://aplus.rs/images/2011/customer_ipad_sleevecase_vertical_ipad_lg.jpg" alt="" /></p>

<p>Thus after checking out few other bags, I decided on WaterField&#8217;s. They offer several bag options for iPad and after checking out each, decided on <a href="http://sfbags.com/products/ipad-cases/sleevecases-ipad.php">Ultimate model</a>. I especially liked the vertical model, as I could see it fitting perfectly on the side and not dangling back and forth as I walk and getting in the way of my hands. I picked up the larger piggy back case as well, shoulder strap.</p>

<p>I had no problem to use my Serbian card, which was great. I was ordering about a week before the date when it needed to arrive. My cousins were in New York and the bag simply had to be there at least a day before so they could pack it up in time. The first hurdle was the email I received from Waterfield - the vertical bag was out of stock and it could be several days before they had them made. Unfortunately, this moved the delivery date past my D-day. Waterfield offered to upgrade the shipping up, with no extra charge, but it still ended up a day short. So I opted for the 2-day delivery which added 20$. As luck would have it, my cousins eventually stayed for another week, due to Iceland volcano eruption. Such as life…</p>

<p>The bag itself is amazing. Just as I thought, the vertical orientation is perfect and sits so good on the side that it does not get in the way at all. The fit is perfect, snug but not too tight, so it&#8217;s easy to put the iPad inside. The interior is padded with soft cloth that can wipe the iPad screen; don&#8217;t expect wonders though. In the back they added a tight pocket where you can fit a real wipe cloth, a few pieces of paper or something similarly thin.</p>

<blockquote><p>I had this bag for over a year now, it&#8217;s looking great (especially the worn leather look it gains over time) and no defects nor malfunctions.</p></blockquote>

<p>The bag is really sturdy and re-enforced on the edges. I can&#8217;t stress enough how important that is - if the bag is ever dropped, I&#8217;m pretty sure it will protect the iPad even from several meters high.</p>

<p>The piggy back case is very simple, obviously aimed for carrying the wall charger and cables and maybe few more simple items. It was one flaw though - the material it&#8217;s made from is the same as the sleeve case. When two of these rubs during walking, they make very annoying sound, especially inside the hallways where it&#8217;s sufficiently silent environment. Solution would be to have very small piece of velcro on the back of the piggy case that will attach itself to the main bag.</p>

<p>I plan to do this myself, once I have the time.</p>

<p>In the meantime, I&#8217;m using my old usual carry around little bag, which can attach to the iPad bag perfectly. This way I carry these two using one shoulder strap and I can detach the smaller bag when needed and carry just it. Perfect combination.</p>

<p>I&#8217;m very happy with the bag and would recommend it to any iPad owner. Without the piggy back case though, at least until Waterfield does something about the noise.</p>

<p>In the mean time, being so happy with this bag, I ordered a whole set of bags and sleeves for the laptops. I got the <a href="http://www.sfbags.com/products/laptopsuedejacket/laptopsuedejacket.htm">Suede Jacket sleeve</a> case for both mine and my wife&#8217;s notebooks and also <a href="http://www.sfbags.com/products/vertigo/vertigo.htm">Vertigo</a> vertical bags (seriously, don&#8217;t ever buy horizontal orientation ever).</p>

<p>Could not be happier with any of these and I plan to keep getting their stuff.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Carefree musings on Apple TV]]></title>
    <link href="http://aplus.rs/2011/carefree-musings-on-apple-tv/"/>
    <updated>2011-11-03T17:20:36+01:00</updated>
    <id>http://aplus.rs/2011/carefree-musings-on-apple-tv</id>
    <content type="html"><![CDATA[<p>While listening my favorite podcasts these days, quite a bit of them are discussing this quote from the Steve Jobs biography:</p>

<blockquote><p>I&#8217;d like to create an integrated television set that is completely easy to use. It would be seamlessly synced with all of your devices and with iCloud. It will have the simplest user interface you could imagine. I finally cracked it.</p></blockquote>

<p>Mouth-watering, isn&#8217;t it? Given the fact what was done for phone and tablets, this is beyond interesting. <a href="http://daringfireball.net/2011/10/apps_are_the_new_channels">John Gruber</a>, <a href="http://5by5.tv/buildanalyze/48-zero-inputs">Marco Arment</a> and <a href="http://5by5.tv/hypercritical/40-when-the-hobby-light-goes-off">John Siracusa</a> all shared how they see this working. As usual, I agree with bits from all of the stuff they said, but not all of it (and them do not agree on all counts). There&#8217;s also an oft-linked <a href="http://bits.blogs.nytimes.com/2011/10/27/whats-really-next-for-apple-in-television/?pagewanted=all">NY Times article</a> on Siri as the main interface for this new TV.</p>

<p>Here&#8217;s what I believe will be main features of the future Apple TV business.</p>

<!-- more -->


<p><strong>There will be a physical TV made by Apple.</strong> Probably offered in several typical sizes, with whatever screen technology they choose for it. IT will have integrated their current little black box with the same name, or (more likely) iPad internals. It will of course have new software that will support stuff I&#8217;ll mention in a bit.</p>

<p>It will use a <strong>new remote based on Bluetooth 4.0</strong> + it will have integrated <strong>Siri support</strong>. Siri will be activated either from your existing iOS device (which will previously be connected over Bt4.0 with the TV) or through a button on the new remote. The new non-IR remote will allow you to manage it from anywhere in TV surrounding, not when facing it directly (as you need to do with IR remote).</p>

<p><strong>No cable cards</strong> nor anything like it, only one (or maybe few) HDMI ports so you can plug-in your existing set-top box. They can&#8217;t have all the possible content from the get-go (although I&#8217;m sure they will strive to have lots of it) so they must support existing stuff somehow. Adding HDMI ports is the easiest way and TV software will allow you to switch to that port and then simply be a screen for whatever is there. HDMI can also be used to support gaming consoles and such, but I somehow don&#8217;t see Apple caring much about that.</p>

<p><strong>Channels will become apps.</strong> As Gruber points out, some content producers are already doing this. The issue here is what to do with like 100 apps or who knows how many channels exists around the world, both actual TV stations or shows produced by popular web sites (like Engadget). Well, they already have a solution for this.</p>

<p>Apps will be inside a new special folder I&#8217;ll call <strong>TV stand</strong> which will work exactly like Newstand does now. But it will be enhanced (probably in iOS 6) so that app icons will be <em>live</em>. When you open the folder, it will change from static app icons to <strong>live previews</strong> of whatever is currently broadcasted on that particular app. They already have this on the Mac - live thumbnails in Exposé.</p>

<p>Further, on the TV it will take over entire screen and basically look like a grid of TVs. It will have infinite scroll to support any number of apps and you could easily check out all the stations, all the shows. They might even have two folders, one for live TV and another for periodicals (TV shows and such).</p>

<p>TV stand will feature <strong>subscriptions</strong> just like newsstand and this will deeply integrate with  your existing iTunes season passes and what not. If they go really crazy on this, they could do their own version of what the wonderful <a href="http://plexapp.com/">Plex app</a> (and Boxee and Roku and&#8230;etc) is doing right now and offer full access to everything you have through iCloud. Watch your content (both your local and broadcasted) from any device, at any internet-enabled location.</p>

<p>Each of these channel apps will have full iOS API at their disposal and they could create <strong>interactive content</strong> beyond anything that was possible so far. Imagine viewers calling-in over face time, real-time version of CNN&#8217;s iReport (if they choose to do that) etc.</p>

<p>Air Play will allow <strong>full screen gaming</strong>, basically killing off whatever gaming consoles survive until then. You will use iPhone, iPod touch or iPad as controllers and play on the TV. Alone or with friends. New APIs will enable that. Some apps already offer it (using Bluetooth) - see this <a href="https://www.youtube.com/watch?v=bcSHD-EM2K4">demo trailer</a> for majicJungle&#8217;s wonderful <a href="http://majicjungle.com/chopper2_iphone.html">Chopper 2</a>.</p>

<p>I can dream more, but this is the essence. With this, &#8220;Apple will get into your den&#8221;. Remember that one? :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Guide to symbolicating iPhone app crash logs with Xcode 4.2]]></title>
    <link href="http://aplus.rs/2011/guide-to-symbolicating-iphone-app-crash-logs-with-xcode-4-2/"/>
    <updated>2011-10-29T15:35:28+02:00</updated>
    <id>http://aplus.rs/2011/guide-to-symbolicating-iphone-app-crash-logs-with-xcode-4-2</id>
    <content type="html"><![CDATA[<p>I was recently investigating one very strange crash in an app I&#8217;m working on. The app is distributed ad-hoc (through wonderful TestFlightapp.com) and each release is archived in Xcode 4.2. I got the <code>.crash</code> file from beta tester and dragged it into Xcode&#8217;s Organizer, which did symbolicate everything in the stack <em>except</em> two lines from my code.</p>

<!-- more -->




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>Incident Identifier: 8B369A29-8421-4686-B1F6-9D66524937B5
</span><span class='line'>CrashReporter Key:   746834fde1cb2033d4103df311e8f3b6ee9e8817
</span><span class='line'>Hardware Model:      iPhone3,1
</span><span class='line'>Process:         myApp <span class="o">[</span>74<span class="o">]</span>
</span><span class='line'>Path:            /var/mobile/Applications/78EC36CC-DAF5-4910-9D60-A03DDC8E24BC/myApp.app/myApp
</span><span class='line'>Identifier:      myApp
</span><span class='line'>Version:         ??? <span class="o">(</span>???<span class="o">)</span>
</span><span class='line'>Code Type:       ARM <span class="o">(</span>Native<span class="o">)</span>
</span><span class='line'>Parent Process:  launchd <span class="o">[</span>1<span class="o">]</span>
</span><span class='line'>
</span><span class='line'>Date/Time:       2011-10-27 11:37:55.841 +0100
</span><span class='line'>OS Version:      iPhone OS 4.3.3 <span class="o">(</span>8J2<span class="o">)</span>
</span><span class='line'>Report Version:  104
</span><span class='line'>
</span><span class='line'>Exception Type:  EXC_CRASH <span class="o">(</span>SIGABRT<span class="o">)</span>
</span><span class='line'>Exception Codes: 0x00000000, 0x00000000
</span><span class='line'>Crashed Thread:  0
</span><span class='line'>
</span><span class='line'>Thread 0 name:  Dispatch queue: com.apple.main-thread
</span><span class='line'>Thread 0 Crashed:
</span><span class='line'>0   libsystem_kernel.dylib            0x3657aa1c 0x36569000 + 72220
</span><span class='line'>1   libsystem_c.dylib                 0x366513b4 pthread_kill + 52
</span><span class='line'>2   libsystem_c.dylib                 0x36649bf8 abort + 72
</span><span class='line'>3   libstdc++.6.dylib                 0x36613a64 __gnu_cxx::__verbose_terminate_handler<span class="o">()</span> + 376
</span><span class='line'>4   libobjc.A.dylib                   0x3548806c _objc_terminate + 104
</span><span class='line'>5   libstdc++.6.dylib                 0x36611e36 __cxxabiv1::__terminate<span class="o">(</span>void <span class="o">(</span>*<span class="o">)())</span> + 46
</span><span class='line'>6   libstdc++.6.dylib                 0x36611e8a std::terminate<span class="o">()</span> + 10
</span><span class='line'>7   libstdc++.6.dylib                 0x36611f5a __cxa_throw + 78
</span><span class='line'>8   libobjc.A.dylib                   0x35486c84 objc_exception_throw + 64
</span><span class='line'>9   Foundation                        0x3522d924 __NSThreadPerformPerform + 648
</span><span class='line'>10  CoreFoundation                    0x31942a72 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 6
</span><span class='line'>11  CoreFoundation                    0x31944758 __CFRunLoopDoSources0 + 376
</span><span class='line'>12  CoreFoundation                    0x319454e4 __CFRunLoopRun + 224
</span><span class='line'>13  CoreFoundation                    0x318d5ebc CFRunLoopRunSpecific + 224
</span><span class='line'>14  CoreFoundation                    0x318d5dc4 CFRunLoopRunInMode + 52
</span><span class='line'>15  GraphicsServices                  0x31254418 GSEventRunModal + 108
</span><span class='line'>16  GraphicsServices                  0x312544c4 GSEventRun + 56
</span><span class='line'>17  UIKit                             0x319fbd62 -<span class="o">[</span>UIApplication _run<span class="o">]</span> + 398
</span><span class='line'>18  UIKit                             0x319f9800 UIApplicationMain + 664
</span><span class='line'>19  myApp                         0x00003a4c main <span class="o">(</span>main.m:14<span class="o">)</span>
</span><span class='line'>20  myApp                         0x00003a04 0x1000 + 10756
</span><span class='line'>
</span><span class='line'>...
</span><span class='line'>
</span><span class='line'>Binary Images:
</span><span class='line'>    0x1000 -    0x67fff +myApp armv7  &lt;a0b39fab741e34eb831048cc752d8e0c&gt; /var/mobile/Applications/78EC36CC-DAF5-4910-9D60-A03DDC8E24BC/myApp.app/myApp
</span></code></pre></td></tr></table></div></figure>


<p>Great. The usual reason for this is that Xcode did not find <code>.dSYM</code> file. This is actually really strange since Xcode has the <code>.xcarchive</code>, saved in its default location. But no matter what I tried, it did not symbolicate properly. One possible reason that I&#8217;ve seen people mention is that Spotlight has not indexed the archives and you can force this with this Terminal command:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>mdimport ~/Library/Developer/Xcode/Archives/
</span></code></pre></td></tr></table></div></figure>


<p>This did not help either. I tested Spotlight and strangely it could not find the app signature (from the bottom of the crash log excerpt above):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>mdfind <span class="s2">&quot;com_apple_xcode_dsym_uuids == A06EC84E-53BF-3209-8B63-C0CAEBDB45B6&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>At this point I tried to do it manually and in series of attemps encountered all kind of possible issues.</p>

<p><strong>First</strong>, I had a custom <code>symbolicatecrash</code> script in <code>/usr/local/bin/</code> from several months ago. This script often changes as Apple devs fix bugs in it. While they do that and ship the fixed version with next Xcode update, good souls on the internet have already resolved the given issue. Thus at some point I downloaded one of those custom versions and placed it there. Hence when I tried to run <code>symbolicatecrash</code> manually, it used that version. You can check this in Terminal, by typing <code>which symbolicatecrash</code> - if it finds the script anywhere in your default paths, it will show it. If not, then you are ok.</p>

<p><strong>Second</strong>, in Xcode 4.2, the current version of this script is at this location: <code>/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash</code>. Files in this private framework are not accessible from any other folder, so in order to run it manually you need to either use this full path or copy it to the folder where you acquired <code>.crash</code> log files are and run it from there.</p>

<p><strong>Third</strong>, I extracted the .app and .dSYM file from the archive and placed in the same folder. I then tried to run the script from there, with all of these line (one by one):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>./symbolicatecrash -v *.crash . &gt; s.crash
</span><span class='line'>./symbolicatecrash -A -v myApp_2011-10-27-113755_Alex-iPhone.crash myApp.app.dSYM &gt; s.crash
</span></code></pre></td></tr></table></div></figure>


<p>None did anything differently. Things began to look really crazy at this point and I started doubting is this a crash report really from this version. Double-checked with tester, also double checked the .app.dSYM file as described <a href="http://stackoverflow.com/questions/6655748/force-symbolicatecrash-to-use-a-specific-app-and-dsym-file">here on Stack Overflow</a>. All was fine, this was the binary used.</p>

<p><strong>Forth</strong>, I tried to directly look for the given hex address in the crash log:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>dwarfdump --lookup 0x00003a04 --arch armv6 myApp.app.dSYM
</span></code></pre></td></tr></table></div></figure>


<p>And this finally gave me what I needed:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>----------------------------------------------------------------------
</span><span class='line'> File: myApp.app.dSYM/Contents/Resources/DWARF/myApp <span class="o">(</span>armv6<span class="o">)</span>
</span><span class='line'>----------------------------------------------------------------------
</span><span class='line'>Looking up address: 0x0000000000003a04 in .debug_info... found!
</span><span class='line'>0x0000012c: Compile Unit: <span class="nv">length</span> <span class="o">=</span> 0x00005a18  <span class="nv">version</span> <span class="o">=</span> 0x0002  <span class="nv">abbr_offset</span> <span class="o">=</span> 0x00000000  <span class="nv">addr_size</span> <span class="o">=</span> 0x04  <span class="o">(</span>next CU at 0x00005b48<span class="o">)</span>
</span><span class='line'>0x00000137: TAG_compile_unit <span class="o">[</span>1<span class="o">]</span> *
</span><span class='line'>             AT_producer<span class="o">(</span> <span class="s2">&quot;Apple clang version 3.0 (tags/Apple/clang-211.9) (based on LLVM 3.0svn)&quot;</span> <span class="o">)</span>
</span><span class='line'>             AT_language<span class="o">(</span> DW_LANG_ObjC <span class="o">)</span>
</span><span class='line'>             AT_name<span class="o">(</span> <span class="s2">&quot;/Users/aleck/dev/consulting/myApp/trunk/Classes/AppDelegate.m&quot;</span> <span class="o">)</span>
</span><span class='line'>             AT_entry_pc<span class="o">(</span> 0x0000323c <span class="o">)</span>
</span><span class='line'>             AT_stmt_list<span class="o">(</span> 0x00000112 <span class="o">)</span>
</span><span class='line'>             AT_comp_dir<span class="o">(</span> <span class="s2">&quot;/Users/aleck/dev/consulting/myApp/trunk&quot;</span> <span class="o">)</span>
</span><span class='line'>             AT_APPLE_optimized<span class="o">(</span> 0x01 <span class="o">)</span>
</span><span class='line'>             AT_APPLE_major_runtime_vers<span class="o">(</span> 0x02 <span class="o">)</span>
</span><span class='line'>
</span><span class='line'>0x00000dc3:     TAG_subprogram <span class="o">[</span>15<span class="o">]</span> *
</span><span class='line'>                 AT_sibling<span class="o">(</span> <span class="o">{</span>0x00000dfb<span class="o">}</span> <span class="o">)</span>
</span><span class='line'>                 AT_name<span class="o">(</span> <span class="s2">&quot;-[AppDelegate dealloc]&quot;</span> <span class="o">)</span>
</span><span class='line'>                 AT_decl_file<span class="o">(</span> <span class="s2">&quot;/Users/aleck/dev/consulting/myApp/trunk/Classes/AppDelegate.m&quot;</span> <span class="o">)</span>
</span><span class='line'>                 AT_decl_line<span class="o">(</span> 250 <span class="o">)</span>
</span><span class='line'>                 AT_prototyped<span class="o">(</span> 0x01 <span class="o">)</span>
</span><span class='line'>                 AT_APPLE_isa<span class="o">(</span> 0x01 <span class="o">)</span>
</span><span class='line'>                 AT_low_pc<span class="o">(</span> 0x000039d4 <span class="o">)</span>
</span><span class='line'>                 AT_high_pc<span class="o">(</span> 0x00003a6c <span class="o">)</span>
</span><span class='line'>                 AT_frame_base<span class="o">(</span> r7 <span class="o">)</span>
</span><span class='line'>
</span><span class='line'>Line table dir : <span class="s1">&#39;/Users/aleck/dev/consulting/myApp/trunk/Classes&#39;</span>
</span><span class='line'>Line table file: <span class="s1">&#39;AppDelegate.m&#39;</span> line 254, column 5 with start address 0x0000000000003a02
</span><span class='line'>
</span><span class='line'>Looking up address: 0x0000000000003a04 in .debug_frame... found!
</span><span class='line'>
</span><span class='line'>0x00000100: FDE
</span><span class='line'>        length: 0x0000000<span class="sb">```</span> objective-c
</span><span class='line'>   CIE_pointer: 0x00000000
</span><span class='line'>    start_addr: 0x000039d4 -<span class="o">[</span>AppDelegate dealloc<span class="o">]</span>
</span><span class='line'>    range_size: 0x00000098 <span class="o">(</span><span class="nv">end_addr</span> <span class="o">=</span> 0x00003a6c<span class="o">)</span>
</span><span class='line'>  Instructions: 0x000039d4: <span class="nv">CFA</span><span class="o">=</span>4294967295+4294967295
</span></code></pre></td></tr></table></div></figure>


<p>Or so I thought. When I looked into my code at this line, this was in <code>dealloc</code> method, where <code>NSPersistentStoreCoordinator</code> was released. And that was really nutty place to have a bug. At this point I was completely stumped and had no idea what else to try.</p>

<p>Luckily in this case, tester was able to give login credentials so I could repeat the scenario using his data, while debugging the app on the device. And found that I had a badly formatted NSPredicate which worked in 99.9% of cases and this tester stumbled on 0.1% where it did not. Great find, it would be a serious head-scratcher if app went live with this.</p>

<p>But I still don&#8217;t understand why Xcode 4.2 won&#8217;t see the <code>.dSYM</code> file and while the script itself won&#8217;t symbolicate this <code>.crash</code> log. Honestly, I can&#8217;t help but think this is seriously more complicated than it needs be. But it is as it is. Here some other useful stuff I encountered while working on this.</p>

<p>Place where Xcode puts <code>.crash</code> logs picked from your testing devices: <code>~/Library/Logs/CrashReporter/MobileDevice/&lt;your device name&gt;.symbolicated</code></p>

<p>Various possibly helpful links:</p>

<p>· <a href="http://www.goosoftware.co.uk/blog/the-symbolicator-helps-those-who-help-themselves/">http://www.goosoftware.co.uk/blog/the-symbolicator-helps-those-who-help-themselves/</a></p>

<p>· <a href="https://devforums.apple.com/message/404524">https://devforums.apple.com/message/404524</a></p>

<p>· <a href="http://stackoverflow.com/questions/2697067/symbolicate-adhoc-iphone-app-crashes">http://stackoverflow.com/questions/2697067/symbolicate-adhoc-iphone-app-crashes</a></p>

<p>If you have any ideas that could help, please write in comments.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The thin fun line]]></title>
    <link href="http://aplus.rs/2011/the-thin-fun-line/"/>
    <updated>2011-04-20T14:57:10+02:00</updated>
    <id>http://aplus.rs/2011/the-thin-fun-line</id>
    <content type="html"><![CDATA[<p>In the last few days, there&#8217;s been quite a storm in the Twitter tea pot, regarding the new hit iOS client, <a href="http://tapbots.com/software/tweetbot/">Tweetbot</a>. All Tapbots apps have completely custom UI, sounds and interaction but they always managed to make it so and still keep great performance. This is the main reason for their success - the fun part in using them did not come with a price (like UI lag).</p>

<p>However, Tweetbot faces quite a bit criticism that its custom UI hinders the UX of the app.</p>

<!-- more -->


<p>Many things have been said regarding this but I find Ben Brooks&#8217; series of complaint posts particularly misplaced. He <a href="http://brooksreview.net/2011/04/sperte-ui/">argues</a> that Tweetbot&#8217;s custom UI over-compliates the things without bringing anything in. He&#8217;s wrong, especially this:</p>

<blockquote><p>&#8220;Gestures in the case of Tweetbot aren’t adding anything to the all important UX — in fact I would think they are detracting from it by straying so far from conventional iOS norms.&#8221;</p></blockquote>

<p>Tweetbot isn&#8217;t forcing you to learn anything new. You can use the entire app with one and only gesture every single iPhone user knows - simple short tap. Tap to reveal most-used actions over a tweet. Tap the view button to load the tweet in full-screen view and reveal additional options (conversation, related tweets, block/spam report etc).</p>

<p>What I would have liked is that Mark Jardine has not used an eye for this icon, but instead used the default disclosure indicator, like this:</p>

<p><img src="http://aplus.rs/images/2011/Tweetbot-IMG_1037-3.png" alt="A better view icon" /></p>

<p>That button moves the view hierarchy further along, so the default system icon should have been used. Apart from this small hickup, the UI/UX in Tweetbot great - lacks nothing, hinders nothing else.</p>

<p>Seriously, just try - you don&#8217;t have to know any of the gestures (swipes, multiple taps or long taps) to use the app. But when you do discover them, you find yourself using the app that much faster.</p>

<ol>
<li><p>User details are one tap on avatar away, important actions over user are one long tap away</p></li>
<li><p>Actions over tweet are one tap away</p></li>
<li><p>Share options are another tap away after the previous one (instapaper, email etc)</p></li>
<li><p>Conversation is one swipe away. Related tweets (answers to the tweet) are one swipe away</p></li>
<li><p>Reply is triple-tap away (in my case)</p></li>
</ol>


<p>etc. I think it&#8217;s clear - the UI is easy to use, learning curve is almost straight line (apart from that eye icon). But the <em>UX is greatly enhanced with gestures</em> and it brings you that wonderful feeling of being proud that you are the power user.</p>

<p>You should also read <a href="http://kaishinlab.com/tweetbot-vs-twitter/">this feature showdown</a> which, in its second part, shows why Tweetbot is so good. It&#8217;s great for reading the timeline and answering here and there. I can&#8217;t imagine anyone (apart from the most egoistical jerks) writing more tweets than reading them, so this is <strong>the</strong> advantage to have. The feature where Tweetbot is able to <em>properly</em> load the part of the timeline you may have missed during the night is invaluable to me. Official Twitter client often loads this and then loses my place where I was so I have to scroll and find the last tweet I was on.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OPPO's fantastic support service]]></title>
    <link href="http://aplus.rs/2011/oppos-fantastic-support-service/"/>
    <updated>2011-03-08T02:13:43+01:00</updated>
    <id>http://aplus.rs/2011/oppos-fantastic-support-service</id>
    <content type="html"><![CDATA[<p>I have <a href="http://oppodigital.com/dv981hd/dv981hd_index.asp">OPPO DV-981HD player</a> for several years now. It&#8217;s a great piece of consumer electronics - from the moment I put it on it worked great. No issues, no fuss, it worked exactly as advertised. Until few weeks ago when it died. In the middle of movie, it saved a bookmark and shut down. No reactions to buttons, it just seemed dead.</p>

<p>The player was long ago out of warranty. Plus, I brought it to Serbia from UK, one of the last pieces the importer had. OPPO does have a &#8220;send it to us for repair&#8221; service, but the cost of sending to USA from Serbia would be more than the player is now worth. Plus, experience with other companies tells me that prices for obsolete (OPPO does not sell this model anymore) and out-of-warranty parts are outrageous.</p>

<p>So I emailed OPPO support, simply hoping for an advice what could be wrong so I can try my luck with local repair shops. I was hoping it&#8217;s simply some part of the power board. That was on Saturday afternoon (CET time zone).</p>

<p>This is where it becomes awesome. First, I got answer in less than 24h. Second, the answer said that OPPO can help me by sending me a replacement power board and a front-end display. Third, the price for the parts is mere $49. And then to top it off, they responded to my follow-up questions on Sunday and Monday (which was a bank holiday in US). I paid and they shipped the parts the very next day; the package reached me by the end of the week (sent by USPS).</p>

<p><em>Amazing, amazing support service</em>, way better than I expected. I replaced the parts and the player is working as good as ever - silently and awesomely.</p>

<p>If you are in need of an excellent Blu-ray player, do not even think about anything else - <a href="http://oppodigital.com/">buy one of the OPPO players</a> they have on offer. I&#8217;m certain they are amazing just as this DVD player is. I mean, just look at the feature set, the customer testimonials and rave reviews they consistently get for their products.</p>

<p>We need more companies like OPPO. <em>Kudos, masters.</em></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Fighting feature creep]]></title>
    <link href="http://aplus.rs/2011/fighting-feature-creep/"/>
    <updated>2011-03-07T13:18:11+01:00</updated>
    <id>http://aplus.rs/2011/fighting-feature-creep</id>
    <content type="html"><![CDATA[<p>Feature creep is an easy trap to fall into. As developer and software vendor, you always want to please your users. So when a request comes in and it&#8217;s eloquently and nicely laid out, it&#8217;s hard to resist. I experienced it so much while working on Run Mate 1.1, which is the main reason why it took me 3 months to publish it.</p>

<p>Never again. I hope.</p>

<p>I have a new weapon against it now &#8211; it&#8217;s a wonderful thought that <a href="http://delicious-monster.com/">Wil Shipley</a> said in an interview for <a href="http://www.mac-developer-network.com/">Mac Developer Network</a> podcast:</p>

<blockquote><p>&#8230;Technology is just being too complicated. People just don&#8217;t enjoy using it, they don&#8217;t get it, they&#8217;re not getting the most out of it, they&#8217;re not able to use the feature they have and if we radically simplify it, then people suddenly get a lot more out of it.</p>

<p><strong>They actually use more features if you give them less features.</strong></p></blockquote>

<p>MDN podcast is wonderful resource. I had a large backlog of various podcasts &#8211; this Shipley interview is in <a href="http://www.mac-developer-network.com/shows/podcasts/mdnshow/mdn003/">MDN Show 003</a> from back in July 2009 &#8211; which I have recently cleared out. I never check what is in any of the shows, I like when they surprise me. This interview with Wil is chock full of great thoughts.</p>

<p>Another fantastic feature of the MDN Show is <em>World according to Gemmell</em> where <a href="http://mattgemmell.com/">Matt Gemmell</a> picks an UX subject and really, really hummers it down.</p>

<p>Note: Steve Scott, the man who ran MDN, has retired that show and now has a new show called <a href="http://ideveloper.tv/shows">iDeveloper Live</a>. It&#8217;s more dynamic than MDN Show (more people) plus it&#8217;s recorded live and you can be part of it through the chat.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Debugging [CALayer retain]: message sent to deallocated instance]]></title>
    <link href="http://aplus.rs/2011/debugging-calayer-retain-message-sent-to-deallocated-instance/"/>
    <updated>2011-03-04T03:32:51+01:00</updated>
    <id>http://aplus.rs/2011/debugging-calayer-retain-message-sent-to-deallocated-instance</id>
    <content type="html"><![CDATA[<p>While working recently on an iPhone app, I had a subclass of UITableViewCell with a specific indicator, all defined like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@interface</span> <span class="nc">EmailListCell</span> : <span class="nc">UITableViewCell</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">UIImageView</span> <span class="o">*</span><span class="n">indicator</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">@property</span> <span class="p">(</span><span class="n">nonatomic</span><span class="p">,</span> <span class="n">retain</span><span class="p">)</span> <span class="n">UIImageView</span> <span class="o">*</span><span class="n">indicator</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>In the implementation part - since the property is retained, I automatically added this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@implementation</span> <span class="nc">EmailListCell</span>
</span><span class='line'>
</span><span class='line'><span class="k">@synthesize</span> <span class="n">indicator</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">dealloc</span> <span class="p">{</span>
</span><span class='line'>  <span class="p">[</span><span class="n">indicator</span> <span class="n">release</span><span class="p">];</span>
</span><span class='line'>  <span class="n">indicator</span> <span class="o">=</span> <span class="nb">nil</span><span class="p">;</span>
</span><span class='line'>  <span class="p">[</span><span class="n">super</span> <span class="n">dealloc</span><span class="p">];</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is what I usually do, mostly mechanically, to not forget to add proper releasing. And it came back to bite me this time.</p>

<p>It was because of the initializing code I wrote after the code above:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nf">initWithStyle:</span><span class="p">(</span><span class="n">UITableViewCellStyle</span><span class="p">)</span><span class="nv">style</span> <span class="nf">reuseIdentifier:</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="nv">reuseIdentifier</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">self</span> <span class="o">=</span> <span class="p">[</span><span class="n">super</span> <span class="nl">initWithStyle:</span><span class="n">style</span> <span class="nl">reuseIdentifier:</span><span class="n">reuseIdentifier</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>      <span class="n">indicator</span> <span class="o">=</span> <span class="p">[[</span><span class="n">UIImageView</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithImage:</span><span class="n">widgetEmpty</span><span class="p">];</span>
</span><span class='line'>      <span class="p">[</span><span class="n">self</span> <span class="nl">addSubview:</span><span class="n">indicator</span><span class="p">];</span>
</span><span class='line'>      <span class="p">[</span><span class="n">indicator</span> <span class="n">release</span><span class="p">];</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="n">self</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>When testing this table view, it would - in some cases only - crash the app, with one of these messages shown:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>*** -<span class="o">[</span>CALayer retain<span class="o">]</span>: message sent to deallocated instance 0x5c73490<span class="sb">`</span>
</span><span class='line'>modifying layer that is being finalized 0x713a170<span class="sb">`</span>
</span></code></pre></td></tr></table></div></figure>


<p>These are thrown when you attempt to access UIView of any sort that is in the process of being deallocated. Catching these things is very tricky, because the objects mentioned are already gone, so even if you setup breakpoint to <code>objc_exception_throw</code>, it won&#8217;t help you much.</p>

<p>So, do you see where the issue is? :)</p>

<p><em>I am releasing indicator view twice</em>. First time when it is created and second time in <code>dealloc</code>. The latter is not needed, since all subviews of the cell&#8217;s view will automatically be released along with it. The code I wrote would be correct if the init line used the property:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="n">self</span><span class="p">.</span><span class="n">indicator</span> <span class="o">=</span> <span class="p">[[</span><span class="n">UIImageView</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithImage:</span><span class="n">widgetEmpty</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>By using <code>self</code>, I&#8217;m actually raising the retain count to 2, so two release calls would be fine. Thus, the proper initialization code would be:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="n">UIImageView</span> <span class="o">*</span><span class="n">ind</span> <span class="o">=</span> <span class="p">[[</span><span class="n">UIImageView</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithImage:</span><span class="n">widgetEmpty</span><span class="p">];</span>
</span><span class='line'><span class="n">self</span><span class="p">.</span><span class="n">indicator</span> <span class="o">=</span> <span class="n">ind</span><span class="p">;</span>
</span><span class='line'><span class="p">[</span><span class="n">self</span> <span class="nl">addSubview:</span><span class="n">ind</span><span class="p">];</span>
</span><span class='line'><span class="p">[</span><span class="n">ind</span> <span class="n">release</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>And then the <code>indicator release</code> in the <code>dealloc</code> is mandatory (and also a proper way when dealing with retained properties).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[iPad 2gen prediction]]></title>
    <link href="http://aplus.rs/2010/ipad-2gen-prediction/"/>
    <updated>2010-08-03T19:39:58+02:00</updated>
    <id>http://aplus.rs/2010/ipad-2gen-prediction</id>
    <content type="html"><![CDATA[<p>When Apple updated screen res of the iPhone 4 to 640x960 on the same 3.5&#8221; (diagonal) form factor as previous iPhones, the magic Retina Display number turned out to be 326ppi (pixels per inch). The result is an awesome display, the best I have ever seen.</p>

<p>iPad on the other hand has 9.7&#8221; (diagonal) with 1024x768 resolution, which gives 132ppi. John Siracusa <a href="http://twitter.com/siracusa/status/20223336428">said</a> that next iPad will most likely have the same improvement in display rez, meaning it will have 2048x1536 - so the iOS4&#8217; <code>@2x</code> API stuff work the same.</p>

<p>Granted, such resolution sounds ginormous - not even Apple&#8217;s latest 27&#8221; monitor is big enough to design interfaces that big. But if that really happen&#8230;</p>

<p>&#8230;how big the iPad would physically needs to be?</p>

<p>iPad has 1.33x aspect ratio and 9.7&#8221; diagonal display now. <code>2048x1536</code> and with <code>326ppi</code> equals to about <code>9650in</code> in one very long line, or divide again to get about <code>29.6in2</code>. From there, the math is easy: <code>1.33x * x = 29.6</code>, means that <code>x</code> is 4.71in and that physical screen size of the Retina Display iPad would be 4.71 x 6.28, or about <strong>7.85&#8221; diagonal</strong>.</p>

<p>Sounds quite possible, does it not?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Color of raw image pixel data and iPhone 4's retina display]]></title>
    <link href="http://aplus.rs/2010/color-of-raw-image-pixel-data-and-iphone-4s-retina-display/"/>
    <updated>2010-07-09T01:47:08+02:00</updated>
    <id>http://aplus.rs/2010/color-of-raw-image-pixel-data-and-iphone-4s-retina-display</id>
    <content type="html"><![CDATA[<p>In my <a href="http://itunes.apple.com/us/app/ambient-mood-lamp/id364250227?mt=8&amp;partnerId=30&amp;siteID=mdLUv0b0uzo">Ambient Mood Lamp</a> app, I have a color picker where you can choose the background color by simply tapping the color on an image, like this:</p>

<p><img src="http://aplus.rs/images/2010/iphone-colorswirl4.png" alt="Color swirl" /></p>

<p>What I need from there is the actual RGB representation of the pixel color. To get that, there&#8217;s quite a bit of code involved. A large part of it is taken from Apple&#8217;s <a href="http://developer.apple.com/mac/library/qa/qa2007/qa1509.html">technical note QA1509</a>.</p>

<p>Pixel color fetching is done in this <code>if</code> block from that article:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="n">data</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// **** You have a pointer to the image data ****</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// **** Do stuff with the data here ****</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>I picked up the code to get the pixel color from some web page I lost track of. This is the code:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="p">((</span><span class="n">w</span><span class="o">*</span><span class="n">round</span><span class="p">(</span><span class="n">point</span><span class="p">.</span><span class="n">y</span><span class="p">))</span><span class="o">+</span><span class="n">round</span><span class="p">(</span><span class="n">point</span><span class="p">.</span><span class="n">x</span><span class="p">))</span> <span class="o">*</span> <span class="mi">4</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">alpha</span> <span class="o">=</span>  <span class="n">data</span><span class="p">[</span><span class="n">offset</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">red</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">green</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">2</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">blue</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">3</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'><span class="n">color</span> <span class="o">=</span> <span class="p">[</span><span class="n">UIColor</span> <span class="nl">colorWithRed:</span><span class="p">(</span><span class="n">red</span><span class="o">/</span><span class="mf">255.0f</span><span class="p">)</span> <span class="nl">green:</span><span class="p">(</span><span class="n">green</span><span class="o">/</span><span class="mf">255.0f</span><span class="p">)</span> <span class="nl">blue:</span><span class="p">(</span><span class="n">blue</span><span class="o">/</span><span class="mf">255.0f</span><span class="p">)</span> <span class="nl">alpha:</span><span class="p">(</span><span class="n">alpha</span><span class="o">/</span><span class="mf">255.0f</span><span class="p">)];</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>w</code> is the width of one row of data, and point <code>{x,y}</code> is where the screen was touched. The <code>* 4</code> in the first line means 4 bytes of raw data per pixel. Well, 4 bytes when your screen res is up to 160ish ppi. On iPhone 4&#8217;s Retina Display, with its 326ppi resolution, this should be 8. Which means correct code now is:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="p">((</span><span class="n">w</span><span class="o">*</span><span class="n">round</span><span class="p">(</span><span class="n">point</span><span class="p">.</span><span class="n">y</span><span class="p">))</span><span class="o">+</span><span class="n">round</span><span class="p">(</span><span class="n">point</span><span class="p">.</span><span class="n">x</span><span class="p">))</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">*</span> <span class="p">[[</span><span class="n">UIScreen</span> <span class="n">mainScreen</span><span class="p">]</span> <span class="n">scale</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>Welcome to wonderful world of resolution independent programming.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Better icons for your iPhone apps on the iPad]]></title>
    <link href="http://aplus.rs/2010/better-icons-for-your-iphone-apps-on-the-ipad/"/>
    <updated>2010-05-23T05:10:10+02:00</updated>
    <id>http://aplus.rs/2010/better-icons-for-your-iphone-apps-on-the-ipad</id>
    <content type="html"><![CDATA[<p>When you have iPhone apps installed on the iPad, chances are they are doubly-ugly: they look pixelated when doubled and their icons are even more ugly extrapolated from 57x57px to 72x72px.</p>

<p>Recently, David Frampton posted <a href="http://www.flickr.com/photos/8953623@N06/4583207492/">great idea</a> how Apple should have done this (the idea got picked by Daring Fireball, TUAW and many others). While idea is great, it&#8217;s more than doubtful that Apple would do this.</p>

<p>What Apple would likely prefer is that you, as developer, make an iPad version of your iPhone app and use the full capability of the device. In the process, you&#8217;ll create proper iPad icons and no ugliness then. In the Apple&#8217;s DevForums, there&#8217;s a <a href="https://devforums.apple.com/thread/43845?tstart=0">thread with guidelines</a> on how to populate <em>App</em>-info.plist file and what icon files are needed.</p>

<p>In there, it says that for iPhone-only apps you need to populate <code>CFBundleIconFile</code> key with 57px icon. However, if you move down a bit, you&#8217;ll find section on setting up universal app. <strong>Do that</strong>, even if your app is not universal and voila - iPad will use the proper icon for your iPhone-only app.</p>

<p><img src="http://aplus.rs/images/2010/Screen-shot-2010-05-23-at-02.33.02.png" alt="Setting up icon meta data, so it displays proper icons on iPhone/iPad" /></p>

<p>The settings above are from my <a href="http://codeaplus.com/quickie/">Quickie to do</a> app - here&#8217;s before and after:</p>

<p><img src="http://aplus.rs/images/2010/Pastebot-2010-05-23-02.32-2.jpg" alt="Quickie icon on the iPad, before and after" /></p>

<p>Much better looking.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Always use isEqualToString for string comparisons]]></title>
    <link href="http://aplus.rs/2010/always-use-isequaltostring-for-string-comparisons/"/>
    <updated>2010-01-09T02:28:10+01:00</updated>
    <id>http://aplus.rs/2010/always-use-isequaltostring-for-string-comparisons</id>
    <content type="html"><![CDATA[<p>While working on my iPhone app <a href="http://radianttap.com/quickie/">Quickie</a>, I encountered one of many examples why you must <em>always check your code on the actual device</em>.</p>

<p>Quickie uses Core Data for storage and in one particular place I was comparing the <code>NSString</code> variable to a <code>NSString</code>-typed property of my CoreData class, <code>QuickieList</code>. Like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="n">QuickieList</span><span class="p">.</span><span class="n">listName</span> <span class="o">!=</span> <span class="n">theListName</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>listName</code> is defined as <code>NSString</code> and <code>theListName</code> is obviously that as well. In this particular instance, both of those had the value of &#8220;test&#8221;.</p>

<p>In the iPhone Simulator (running on 10.6.2) this comparison returned <code>false</code>, but on the iPhone running 3.1.2 it returned <code>true</code>. When changed into:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">[</span><span class="n">QuickieList</span><span class="p">.</span><span class="n">listName</span> <span class="nl">isEqualToString:</span><span class="n">theListName</span><span class="p">])</span>
</span></code></pre></td></tr></table></div></figure>


<p>result was the same.</p>

<p>Never &#8211; I repeat &#8211; <em>never</em> assume that simulator testing will be fine, even for seemingly small things. It can bite you when you least expect it.</p>
]]></content>
  </entry>
  
</feed>
