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

  <title><![CDATA[Dynamic Binding]]></title>
  <link href="http://www.joergjacobsen.com/atom.xml" rel="self"/>
  <link href="http://www.joergjacobsen.com/"/>
  <updated>2013-12-12T11:48:23+01:00</updated>
  <id>http://www.joergjacobsen.com/</id>
  <author>
    <name><![CDATA[Jörg Jacobsen]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[4K Monitor Considerations]]></title>
    <link href="http://www.joergjacobsen.com/blog/2013/12/10/4k-monitor-considerations/"/>
    <updated>2013-12-10T17:01:00+01:00</updated>
    <id>http://www.joergjacobsen.com/blog/2013/12/10/4k-monitor-considerations</id>
    <content type="html"><![CDATA[<p>With the advent of the new Retina Macbook Pros, the new Mac Pro almost here, and Dell announcing new so-called <a href="http://www.dell.com/learn/us/en/uscorp1/secure/2013-12-2-dell-ultrasharp-ultra-hd-monitors">&#8220;4K&#8221; monitor models</a>  at affordable prices more Mac users are considering to get a 4K monitor. It promises a similar display sharpness as the native Retina Macbook Pro displays already offer.</p>

<p>This promise though has recently been discussed controversially (<a href="http://atp.fm/episodes/42-the-ultimate-vanity-search">e.g. ATP</a>) with keywords being Pixel Density, Screen Space, Retina Resolution, HiDPI Modes.</p>

<p>Here is my take.</p>

<!-- more -->


<h2>HiDPI Modes vs. Retina Resolution</h2>

<p>Targeted at their Retina displays Apple has introduced specific screen resolutions they call &#8220;HiDPI Modes&#8221;. Instead of rendering one pixel per point of a user-chosen screen resolution of x by y points these modes render 2 by 2 pixels per point. This naturally results in a much sharper display specifically when using screen resolutions below the physical screen resolution of a display. And this is the standard use case with Retina displays on Macbook Pros and probably 4K displays since they offer such high pixel densities you wouldn&#8217;t want to choose the physical screen resolution as your actual resolution.</p>

<p>There is one specific HiDPI mode referred to as the Retina resolution which is the screen resolution that is exactly half the resolution of the physical screen. I.e. since being HiDPI it renders exactly the amount of pixels of the physical screen. It is sometimes also referred to as the @2x resolution.</p>

<p>Some people argue that this clearly is the preferred resolution to choose from using a retina screen since it best &#8220;matches&#8221; its physical screen resolution (read: delivers the best sharpness). Although mathematically there may be some truth to it I have found that in practice it doesn&#8217;t matter. You will hardly be able to pick any other HiDPI mode OS X provides and call it out to provide less sharpness than the retina resolution. Apple has done a tremendous job on this.</p>

<p>The above being said and assuming HiDPI modes being sufficiently available for a 4K monitor you could argue that</p>

<ul>
<li>In terms of sharpness it is safe to pick higher than retina resolutions on a 4K monitor. Thus, you are not at all constrained to a 1920x1080 points screen space.</li>
<li>Display sharpness then becomes solely a function of physical screen pixel density</li>
</ul>


<h2>HiDPI Modes vs. Performance</h2>

<p>There is of course a performance penalty for using higher resolutions in general and it is the job of the graphics card and the data bus to handle that.</p>

<p>We&#8217;ve got high performance graphics cards and thunderbolt2 delivered with the above mentioned computer models but it seems that much awaited display modes like 2560x1440 HiDPI still surpass their capabilities. Specifically Thunderbolt2 doesn&#8217;t seem capable of transferring 2560x1440 HiDPI mode data at reasonable rates to a monitor (<a href="https://twitter.com/joshjet/status/410093244102352896">See joshjet&#8217;s tweet</a>). And I doubt that HDMI would do any better (but would love to be proven wrong).</p>

<h2>Pixel Density</h2>

<p>Anyhow, If you want to judge roughly what display sharpness you will get from a hypothetical 27&#8221; 4K monitor (it has a pixel density of about 163 ppi) place your non-retina iPad mini at same distance and height in front of you as you place your regular monitor, hook up a keyboard to the iPad and start typing within your preferred editor.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Why The Mac App Store Should Stay Away From Paid Upgrades]]></title>
    <link href="http://www.joergjacobsen.com/blog/2012/03/28/why-the-mac-app-store-should-stay-away-from-paid-upgrades/"/>
    <updated>2012-03-28T15:00:00+02:00</updated>
    <id>http://www.joergjacobsen.com/blog/2012/03/28/why-the-mac-app-store-should-stay-away-from-paid-upgrades</id>
    <content type="html"><![CDATA[<p>Wil Shipley has written an interesting <a href="http://blog.wilshipley.com/2012/03/mac-app-store-needs-paid-upgrades.html">blog post</a> where he strongly argues in favor for the need of paid (discounted) upgrades for apps in the Mac App Store (MAS). He also proposes a solution that features the association of one app with any number of other apps in MAS to facilitate these paid upgrades. While I like his proposal of associating apps with one another I don&#8217;t like his idea of paid upgrades. Here is why.</p>

<!-- more -->


<p>In my understanding such feature goes against the principle of keeping things as simple as possible. Offering the concept of paid upgrades adds complexity to a selling policy. &#8220;Why do I have to pay for this upgrade and not for that one?&#8221; &#8220;Why is this guy eligible for discounted upgrade and I am not?&#8221; I am not saying this is not manageable but do we need paid upgrades? I think not.</p>

<p>Apple itself has long adopted a selling policy for its own sofware products that adheres to the following principles:</p>

<ul>
<li>sell the product at a relatively low price</li>
<li>offer fixes to the product for free</li>
<li>do not offer any discounted upgrades to evolutionary descendants of the product (iWork 09 in that sense is a descendant of iWork 08). This is equivalent to:</li>
<li>let everyone pay the same price for a new product(descendant)</li>
<li>stop selling a product once its descendant product is being sold (there really was enough time to bugfix it)</li>
</ul>


<p>Simple. Here, Apple again lives up to its core value of embracing simplicity. Yet, people argue that customers will not take to pay the same price for a product they already bought an evolutionary ancestor of as somebody else paid who did not. They argue that former customers will feel (or even are?) being ripped off. I my view discussing this issue is a hopeless endeavor because product pricing in the first place is driven by all kind of factors and &#8220;fair&#8221; is most often interpreted as &#8220;marketable&#8221;. I do want to note though that not offering discounted upgrades should make room for a lower product price.</p>

<p>Why do customers feel being ripped off? It is because they are so used to a selling policy that <em>does</em> offer discounted upgrades. But policies are not by nature but offer advantages and disadvantages. It is benficial to a customer not having to deal with the circumstances of &#8220;upgrades&#8221;. The goal of a simpler selling policy is not to generate more revenue for the selling company but to keep things simple. In the end the whole set of customers of a &#8220;series&#8221; of product evolutions should pay the same in total. Individual customers (e.g. the ones that buy the whole series) may pay more than when being offered discounted upgrades. But they are probably also the ones drawing the highest value from the product.</p>

<p>Apple has proven so many times that it&#8217;s worth it to leave legacy behind. And by the way, I never felt ripped off rebuying iWork XY given its relatively low price. And I could even skip one evolutionary step without losing eligibility for a discounted upgrade.</p>

<h3>What is still to be solved?</h3>

<p>First, customers must get the reasoning behind Apple&#8217;s simple selling policy. I my view it is Apple&#8217;s call to reach out and let them know. And yes, app developers are customers. Then product selling companies should chime in.</p>

<p>Second, Apple should provide a means to communicate to existing buyers when a descendant of a bought product has arrived in the App Store and make the transition between product evolutions easy as pie for buyers and developers (even more so in the era of sandboxing). Regarding this Wil Shipley already proposed a good starting point to a solution.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sandboxing and Coping with Different OS X Versions]]></title>
    <link href="http://www.joergjacobsen.com/blog/2012/02/24/sandboxing-and-coping-with-different-os-x-versions/"/>
    <updated>2012-02-24T18:28:00+01:00</updated>
    <id>http://www.joergjacobsen.com/blog/2012/02/24/sandboxing-and-coping-with-different-os-x-versions</id>
    <content type="html"><![CDATA[<p>Apple has stated that as of June 1st this year apps being submitted to the Mac App Store (MAS) must be sandboxed. Developers embracing sandboxing may face major problems to preserve their app&#8217;s functionality especially when supporting different OS X versions.</p>

<p>This is because Apple&#8217;s whole concept of sandboxing/entitlements is not complete and different OS X versions have different suppport for sandboxing.</p>

<p>Let&#8217;s take a closer look at different scenarios.</p>

<!-- more -->


<h2>Supporting 10.6.x</h2>

<p>There is no concept of app sandboxing in 10.6.x. A sandboxed app should run as if not sandboxed. Yet Developers must ensure not to apply sandbox related API (this is developer best practice).</p>

<h2>Supporting 10.7 upto Current OS X Version</h2>

<p>There currently seem to be two main feasible strategies to adopt sandboxing:</p>

<ol>
<li><p>Strategy: &#8220;Early Feedback&#8221; (more predictability, more work)</p>

<ul>
<li>Sandbox your app and give it as broad temporary entitlements as you need</li>
<li>File a radar (<a href="http://bugreport.apple.com">bug report</a>) to Apple justifying your app&#8217;s need to use these temporary entitlements</li>
<li>Submit your app as early as possible to MAS (referring to that bug report) to get early authoritative feedback from Apple</li>
<li>As Apple provides more powerful and reliable sandbox related API adapt your app to those APIs and revoke entitlements you no longer need (before Apple does)</li>
</ul>


<p>BTW: I have not found any recent evidence that Apple would rather grant your app some temporary
entitlement if that entitlement was isolated in a single purpose XPC Service. All questions about this being asked
in Apple&#8217;s developer forum went unanswered (to my knowledge).</p>

<p>This approach is viable only if the following conditions are met:</p>

<ul>
<li>your app&#8217;s needs can be resolved by the available entitlements (either temporary or non temporary) in the OS X version(s) you want to support</li>
<li>Sandbox related or sandbox affected Apple APIs you need to use are already mature in the OS X version(s) you want to support</li>
<li>Apple will provide appropriate APIs to substitute your app&#8217;s temporary entitlements prior to revoking those entitlements from your app</li>
<li>Apple will provide some sort of &#8220;versioned entitlement mechanism&#8221; allowing you to use broader entitlements in OS X versions that do not yet support APIs that are meant to substitute for revoked entitlements</li>
</ul>
</li>
<li><p>Strategy: &#8220;Wait and Wonder&#8221; (less work, less predictability)</p>

<ul>
<li>Do not sandbox your app (immediately)</li>
<li>Only submit bugfix releases to MAS</li>
<li>Once Apple provides sufficiently powerful entitlements and/or reliable APIs to suit your sandboxed app submit it sandboxed to MAS</li>
</ul>


<p>Here, the following conditions must be met:</p>

<ul>
<li>Your non-sandboxed app entered MAS before June 1st.</li>
<li>For some hard to figure out period you are willing to refrain from submitting new versions of your app
that add additional functionality (only bugfix releases permitted)</li>
<li>Apple will provide entitlements or APIs you need to sandbox your app before your customers abandon your app for lack of evolution</li>
<li>Apple will provide some sort of &#8220;versioned sandbox mechanism&#8221; entitling your app to be sandboxed starting only with a specific OS X version. Otherwise you would have to have two different versions of the same app in MAS (one sandoxed, one not) to support &#8216;older&#8217; OS X versions.</li>
</ul>
</li>
</ol>


<p>You will have noticed that either strategy is somewhat depending on versioned sandboxing / versioned entitlements like</p>

<ul>
<li>Don&#8217;t sandbox me if I am running on OS X upto version X.Y.Z (because Apple has not provided enough entitlements/API upto X.Y.Z to support my app)</li>
<li>Give me a temporary entitlement X upto OS X version X.Y.Z and beginning with X.Y.Z+1 revoke X (since Apple has given me some API so I don&#8217;t need X anymore)</li>
</ul>


<p>Apple has not provided such mechanism yet.</p>

<p>If you are an affected developer or you sympathize with an affected developer you should (should I say must?) file a bug report regarding this omission to Apple (e.g. <a href="http://openradar.appspot.com/radar?id=1514411">like Daniel Jalkut did</a>). This will encourage Apple to provide such means with high priority.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[NSTreeController Memory Leaks Data Source Objects]]></title>
    <link href="http://www.joergjacobsen.com/blog/2012/02/01/nstreecontroller-memory-leaks-data-source-objects/"/>
    <updated>2012-02-01T10:43:00+01:00</updated>
    <id>http://www.joergjacobsen.com/blog/2012/02/01/nstreecontroller-memory-leaks-data-source-objects</id>
    <content type="html"><![CDATA[<p>When recently working on the <a href="https://github.com/karelia/iMedia">iMedia Browser</a>, I’ve been struggling with a strange kind of memory leak: whenever I replaced a node in my data source that was bound to an NSTreeController memory consumption on my App went up significantly (up to 20 MB in that case). This was supposed to be a memory consumption invariant operation since that new node was identical to the old one!</p>

<!-- more -->


<p>After thoroughly digging into it and appointing Instruments to help me on this I was finally convinced that my code in fact was balanced in terms of reference counting. This problem was to be blamed on the other usual suspect: Apple. Thanks to the Allocations instrument I finally figured out:</p>

<p>The number of live nodes always increased by at least one after I triggered the node replacement operation if and only if the old node was the selected item in the tree before being replaced. Since the old node was properly released due to being removed from the array it was (solely) referenced from the only possible explanation was that the associated NSTreeController was still retaining it.</p>

<p>I know, it’s a widespread vice of looking for somebody else to blame instead of keeping your own backyard tidy, but a small test project I set up makes it rather obvious that NSTreeController (as of 10.7.2) is in fact to be held accountable for this leakage. Luckily, there is a simple workaround to the problem which is to programmatically deselect a node in the NSTreeController before replacing it.</p>

<p>If you are interested in the sweaty details find them <a href="https://github.com/jjac/TreeControllerTest">here</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Managing Toll-free Bridging in an ARC’ed Environment]]></title>
    <link href="http://www.joergjacobsen.com/blog/2011/10/05/managing-toll-free-bridging-in-an-arced-environment/"/>
    <updated>2011-10-05T10:44:00+02:00</updated>
    <id>http://www.joergjacobsen.com/blog/2011/10/05/managing-toll-free-bridging-in-an-arced-environment</id>
    <content type="html"><![CDATA[<p>Sooner or later every Objective-C programmer moving to ARC will be confronted with the unhappy compiler requesting him to perform a so-called “bridged cast” where he once did a “toll-free” cast between Objective-C object pointers and pointers to C types like CoreFoundation types. Unfortunately Apple’s documentation on this topic doesn’t cut it yet.</p>

<!-- more -->


<p>Fortunately the ever knowledgeable Mike Ash has written an excellent <a href="http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html">blog post on ARC</a> as a whole and toll-free bridging in particular which I strongly recommend to read. Drawing on this I will rephrase the bottom line on bridged casts in a rather informal but still catchy manner right here.</p>

<p>So, what is ARC concerned about when your program turns an Objective-C object pointer into some C type pointer and vice versa? It’s interest is all about:</p>

<p>Who takes care of releasing that object later on? You the programmer or me, ARC?</p>

<p>Well, you can tell ARC via the following cast modifiers:</p>

<p><strong>__bridge_retained</strong> (n.b.: only use it when casting from object pointer to C type pointer): I (the programmer) need to reference this object for some time in the dark world of C type pointers which is opaque to you, ARC. So please, please do not release this object while I still need it. I (the programmer) promise to release it myself (in the dark world) when I’m done with it</p>

<p><strong>__bridge_transfer</strong> (n.b.: only use it when casting from C type pointer to object pointer): I (the programmer) hand over to you, ARC, an object that I own and that I am no longer interested in in the dark world of C type pointers that is opaque to you. Whenever you, ARC, are done with that object please release it yourself, because you know the right time and thus save me some work not having to do it myself.</p>

<p><strong>__bridge</strong>: ARC, you keep balancing out your retains and releases as I keep balancing out mine in the dark world of C type pointers which is…. Whenever I need to hold on to an object in the dark world I will retain it myself and release it when appropriate. I don’t need any extra contract with you, ARC.</p>

<p>Mike Ash also excercises excellent examples to illustrate these three semantics.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using Badges in the iMedia Browser]]></title>
    <link href="http://www.joergjacobsen.com/blog/2011/06/29/using-badges-in-the-imedia-browser/"/>
    <updated>2011-06-29T10:44:00+02:00</updated>
    <id>http://www.joergjacobsen.com/blog/2011/06/29/using-badges-in-the-imedia-browser</id>
    <content type="html"><![CDATA[<p>I have just finished implementing a long awaited feature for the <a href="https://github.com/karelia/iMedia">iMedia browser</a> called “badges”. You can now annotate your media representations in the browser with badges as shown in the screenshot on the right. Since it is up to the host application to provide specific badges all different kinds of additional information can be communicated to the user through them (e.g. “You have used this media item in the context of this app (n-times)”. A user will also be able to filter the currently displayed image representations with the filters “Show Badged Only” and “Show Unbadged Only”.</p>

<!-- more -->


<p>As a host application’s programmer you have to exercise the following steps to utilize this functionality.</p>

<ol>
<li><p>Implement the following method in your host application’s delegate <IMBObjectViewControllerDelegate> for the iMedia browser:</p>

<p><code>- (CGImageRef) objectViewController:(IMBObjectViewController*) inController badgeForObject:(IMBObject*) inObject</code></p>

<p>Given an object and a corresponding controller you will have to provide a badge image back to the browser. A typical badge would be a checkmark or a circled number (denoting things like “Item is being used” or “Item is being used n times”). If you return NULL the object won’t be badged. Most often you will keep a dictionary around holding those objects to be badged keyed by some object identifier that is also known to the respective object inside the browser (-[IMBObject identifier] would be such a key candidate).</p>

<p>The badge image will be drawn in 3 different views that embed media objects: the icon view (≥ OSX 10.6), the list view and the combo view. Because the list view sports a mere height of 17 pixels per row and since badge images will not be scaled in any way by the browser framework an image size of 16 pixels square is generally a good choice. You find an exemplary implementation of the method in IMBTestAppDelegate.</p>

<p>To keep your implementation of the method performant (it will get called at least once on any object to be displayed) it is good practice to cache badge images.</p></li>
<li><p>To signal changes on badges to the framework send a</p>

<p><code>setObjectContainerViewNeedsDisplay:YES</code></p>

<p>message to all IMBNodeViewController objects that your app instantiated. If you intended to implement the “Item is being used” type of badge a typical initial badge-changing trigger would be a drag and drop operation of media objects from the browser into a view of your app (see an exemplary implementation on how to handle that in IMBTestTextView. Subsequent possibly badge-changing (user) actions then would be (list considered incomplete):</p>

<ul>
<li>Discard a media object from the app</li>
<li>Undo/redo a drag and drop operation</li>
</ul>
</li>
</ol>


<p>It is definitely the host application’s programmer’s responsibility to attach a notification to the framework to such actions. Note that handling of the actions from above is not excercised by the browser test app.</p>

<h2>For the More Curious: Behind the Scenes</h2>

<p>Responsibilities for getting badges to work are shared among a couple of objects:</p>

<ul>
<li><p><strong>An IMBNodeViewController</strong>: tells its currently visible object view that it must redraw itself (triggered by the host application)<br/>
→ <code>setObjectContainerViewNeedsDisplay:</code></p></li>
<li><p><strong>An IMBObjectViewController</strong>: is the one that asks its delegate for an appropriate badge whenever an object will have to be displayed or when it is to be decided wether the object will be displayed at all (badge related filters). Being the view’s delegate it prepares the view (resp. a view cell) for drawing.<br/>
→ <code>willDisplayCell:forTableColumn:row:</code><br/>
→ <code>objectArrayController:filterObject:</code><br/>
→ <code>-[&lt;IMBObjectViewControllerDelegate&gt; objectViewController:badgeForObject:]</code></p></li>
<li><p><strong>An IMBObjectArrayController</strong>: asks the object controller whether an object passes the badge filter test.<br/>
→ <code>arrangeObjects:</code></p></li>
<li><p><strong>A View</strong>: can be either an IMBImageBrowserView, an IMBComboTableView, or an IMBDynamicTableView. It is responsible for actually drawing the badge it got via the controller.<br/>
→ <code>-[IMBImageBrowserCell layerForType:]</code><br/>
→ <code>-[IMBComboTextCell _drawImage:withFrame:]</code></p></li>
</ul>


<p>It is worth mentioning that the framework does not keep any badging information in its state (aside from a volatile reference to a badge image in a view cell). Thus, the framework must always query the host application’s delegate for appropriate badges. The upside of this design decision is that it is easier to keep the framework’s and the host application’s state in sync compared to storing badge information with the framework’s media objects. The downside obviously is that it is less performant.</p>
]]></content>
  </entry>
  
</feed>
