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

  <title><![CDATA[Use Your Loaf]]></title>
  <link href="http://useyourloaf.com/blog/atom.xml" rel="self"/>
  <link href="http://useyourloaf.com/"/>
  <updated>2013-05-23T23:45:26+01:00</updated>
  <id>http://useyourloaf.com/</id>
  <author>
    <name><![CDATA[Keith Harrison]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Restoration Classes and UIWebViews]]></title>
    
      <category term="State Restoration"/>
    
      <category term="iOS 6"/>
    
    <link href="http://useyourloaf.com/blog/2013/05/23/restoration-classes-and-uiwebviews.html"/>
    <updated>2013-05-23T21:10:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2013/05/23/restoration-classes-and-uiwebviews</id>
    <content type="html"><![CDATA[<p>I previously covered the basics of using <a href="http://useyourloaf.com/blog/2013/05/21/state-preservation-and-restoration.html">state preservation and restoration</a> but for the sake of brevity I did not provide an example of how to use a Restoration Class. This post will fix that omission and also take a look at how you can implement state restoration for a UIWebView.</p>

<h3>A Quick Recap</h3>

<p>If you need a recap on the basics of state preservation and restoration you should refer back to the <a href="http://useyourloaf.com/blog/2013/05/21/state-preservation-and-restoration.html">previous post</a>. In brief though the key points are as follows:</p>

<ul>
<li>The Application Delegate must opt-in</li>
<li>All View Controllers and Views to be preserved/restored must have a restoration identifier.</li>
<li>View Controllers which are part of the main storyboard or Nib file will be created on restoration as part of the application launch.</li>
<li>View Controllers which are not otherwise created on application launch should either implement a restoration class or rely on the Application Delegate to create them.</li>
<li>For restored view controllers implement encodeRestorableStateWithCoder: and decodeRestorableStateWithCoder: where necessary to also restore the state of the view controller.</li>
</ul>


<p>The rest of this post is going to examine the situation where we need a restoration class to restore a view controller by building on the <a href="https://github.com/kharrison/CodeExamples/tree/master/Restorer">example App</a> I introduced in the last post.</p>

<h3>Using A Restoration Class</h3>

<p>Up to now all of the view controllers in our sample App are contained in the main storyboard. This means that once we have assigned restoration identifiers they will all get restored with the Storyboard on application launch.</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-05-20-002.png" alt="" /></p>

<p>To illustrate the use of a restoration class to restore a view controller that is not loaded as part of the storyboard I have added a button to the settings screen which can be used to display a web view:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-05-21-001.png" alt="" />
<img src="http://useyourloaf.com/assets/images/2013/2013-05-23-001.png" alt="" /></p>

<p>The action method invoked by the button creates a new view controller from a Nib file which is used to show the web view. The view controller is pushed onto the existing navigation controller stack and an initial page is loaded:</p>

<pre><code>- (IBAction)pushMe
{
  UYLWebViewController *wvc = [[UYLWebViewController alloc] initWithNibName:@"UYLWebViewController" bundle:nil];
  wvc.restorationIdentifier = @"UYLWebViewController";
  wvc.restorationClass = [UYLWebViewController class];
  [self.navigationController pushViewController:wvc animated:YES];
  [wvc showPage:@"http://useyourloaf.com"];
}
</code></pre>

<p>Note that we set the restoration identifier of the view controller to indicate that we want it restored. We also need to set the restoration class that will take care of creating the new instance of the controller during a restore - it is common to have a class act as its own restoration class. We will see how to implement the restoration class in a moment but we also want to restore the state of the web view. Luckily the UIWebView class already takes care of restoring itself, the details are in the UIKit documentation:</p>

<blockquote><p>In iOS 6 and later, if you assign a value to this view’s restorationIdentifier property, it attempts to preserve its URL history, the scaling and scrolling positions for each page, and information about which page is currently being viewed. During restoration, the view restores these values so that the web content appears just as it did before.</p></blockquote>

<p>We can set the restoration identifier of the UIWebView in the Nib file:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-05-21-002.png" alt="" /></p>

<p>To implement the restoration class we need the web view controller to adopt the UIViewControllerRestoration protocol:</p>

<pre><code>@interface UYLWebViewController () &lt;UIViewControllerRestoration&gt;
</code></pre>

<p>We then need to implement the class method to actually create the new instance of a view controller:</p>

<pre><code>+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
  UIViewController *viewController = [[UYLWebViewController alloc] initWithNibName:@"UYLWebViewController" bundle:nil];
  viewController.restorationIdentifier = [identifierComponents lastObject];
  viewController.restorationClass = [UYLWebViewController class];
  return viewController;
}
</code></pre>

<p>Note that we need to remember to set the restorationIdentifier and restorationClass when we create the restored view controller. You can get the restorationIdentifier from the last object of the array of identifier components.</p>

<p>Now during application restoration when UIKit encounters the restoration identifier of this web view controller it will invoke the restoration class method to create a new instance of the class. Note that if we have view controller state to restore we would do that by implementing the encodeRestorableStateWithCoder: and decodeRestorableStateWithCoder: methods.</p>

<p>At this point you can build and run the app, navigate to the settings tab and use the button to display the web view. If you background the App and use Xcode to stop and then relaunch you should see the web view restored. However what I find actually happens is that the web view appears to be blank. I am not sure if this intended behaviour but it seems to require that the web view is reloaded after restoring the state.</p>

<h3>Restoring the State of a UIWebView</h3>

<p>What we need to do is force a reload of the web view when we are restoring state. One way we can do that is to introduce an instance variable to indicate when we are performing a restoration:</p>

<pre><code>@property (nonatomic) BOOL restoringState;
</code></pre>

<p>We can then implement decodeRestorableStateWithCoder: to flag when we are doing a restore (remembering that we always need to call super):</p>

<pre><code>- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
  [super decodeRestorableStateWithCoder:coder];
  self.restoringState = YES;
}
</code></pre>

<p>Now we can test for a restore in viewDidAppear: and force the reload:</p>

<pre><code>- (void)viewDidAppear:(BOOL)animated
{
  [super viewDidAppear:animated];
  if (self.restoringState)
  {
    [self.webView reload];
    self.restoringState = NO;
  }
}
</code></pre>

<p>Now when you test restoration of the web view you should find that the URL, scaling and scrolling positions are indeed restored.</p>

<h3>Wrapping Up</h3>

<p>As I play more with state restoration I am finding that getting the basics to work is pretty straightforward. However as in this example with a UIWebView and as we saw previously with <a href="http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller.html">table views</a> embedded in a navigation controller there are a few rough edges. You can find the updated version of the <a href="https://github.com/kharrison/CodeExamples/tree/master/Restorer">Restorer</a> Xcode project in my <a href="https://github.com/kharrison/CodeExamples">GitHub CodeExamples</a> repository.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2013/05/23/restoration-classes-and-uiwebviews.html">Restoration Classes and UIWebViews</a> was originally posted 23 May 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[State Preservation and Restoration]]></title>
    
      <category term="State Restoration"/>
    
      <category term="iOS 6"/>
    
    <link href="http://useyourloaf.com/blog/2013/05/21/state-preservation-and-restoration.html"/>
    <updated>2013-05-21T12:00:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2013/05/21/state-preservation-and-restoration</id>
    <content type="html"><![CDATA[<p>From the very first releases of the iPhone SDK Apple has encouraged developers to think about app startup and switching to make the experience as quick and transparent as possible for the user. The limited resources of mobile devices mean that App termination is a common occurrence. Returning to a previously running App that has been terminated by the system and finding it back at a startup screen is not a great user experience. The ability for an App to be suspended and resumed was introduced with iOS 4 and helps to reduce the problem but to make App termination transparent to the end user still takes developer effort.</p>

<p>There is a non-trivial amount of work required to save and then restore a deeply nested hierarchy of views and view controllers. Luckily with iOS 6 direct UIKit support for state preservation and restoration was introduced. This post is a collection of my notes on the basic steps to implement state preservation and restoration.</p>

<h3>State Restoration Flowchart</h3>

<p>A key point to understand about the way UIKit implements state preservation is that it happens when the App moves to the background. You indicate to UIKit which view controllers and views you want to preserve by assigning them restoration identifiers and UIKit then does the hard work of saving the necessary data to an archive file. If the App is then terminated by the system whilst it is suspended the saved archive can be used to restore the App state the next time it is launched.</p>

<p>The state restoration process is controlled by a series of interactions between UIKit, the Application Delegate and the preserved view controllers and views as summarised in the following flowchart:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/StateRestoration.png" alt="State Restoration" /></p>

<h3>A Simple Example</h3>

<p>As always it is easier to show the key concepts by way of example so here is a
very simple example application with only a few UI elements. The main user interface is a tab-bar controller with two tab-bar items. The first tab is a table view controller embedded in a navigation controller. The table view shows a list of countries, selecting a row navigates to a detailed view controller showing details about the country. The second tab is a settings view containing a single UISwitch.</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-05-19-001.png" alt="" />
<img src="http://useyourloaf.com/assets/images/2013/2013-05-19-002.png" alt="" /></p>

<p>The following application state should be restored when the App is launched:</p>

<ul>
<li>The selected tab in the tab-bar should be restored.</li>
<li>Scroll position and any selection of the table view should be restored</li>
<li>Navigation hierarchy of the Navigation Controller (the table view or detailed view may be visible).</li>
</ul>


<p>This is a good point to differentiate between an applications data model and user interface state. The state preservation and restoration system is intended to take care of the user interface state. As we will see shortly the state preservation data will be deleted if the user force-quits the App or if the restoration process fails. You should therefore NOT attempt to use it to store the applications data model. The data model is best stored to a persistent data store for example by writing it to a file, database or something like Core Data. When a view is restored it can of course make use of the persistent data model to correctly configure the restored view.</p>

<p>In this simple example the table view data source is loaded from a plist file and the current state of the settings are saved to the user defaults (using NSUserDefaults). The state of the switch is initialised when the settings view is loaded and saved any time it changes:</p>

<pre><code>- (void)viewDidLoad
{
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  self.amazingSwitch.on = [defaults boolForKey:kUYLSettingsAmazingKey];
}

- (IBAction)amazingAction
{
  BOOL amazingEnabled = self.amazingSwitch.isOn;
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults setBool:amazingEnabled forKey:kUYLSettingsAmazingKey];
  [defaults synchronize];
}
</code></pre>

<h3>Changes To The Application Delegate Launch Process</h3>

<p>If you refer back to the earlier flowchart you will see that with iOS 6 there are now two methods available in the application delegate to initialise the App post launch:</p>

<ul>
<li>application:willFinishLaunchingWithOptions:</li>
<li>application:didFinishLaunchingWithOptions:</li>
</ul>


<p>The major difference between these two methods is that the &#8220;willFinish&#8221; method, which is new in iOS 6, is called before state restoration is performed. The &#8220;didFinish&#8221; method is called after any state restoration has occurred. As a general guideline you will want to perform most application initialisation before state restoration takes place so that things such as the data model are available when the view controllers are restored.</p>

<p>If you have an existing App that has initialisation code in application:didFinishLaunchingWithOptions: you can mostly just move this code to the new application:willFinishLaunchingWithOptions: method. However you need to be careful if you want backward compatibility to iOS 5 or earlier versions as the &#8220;willFinish&#8221; method will never be invoked. One approach is to move everything to a common initialisation method and invoke it from both methods. You can further wrap the initialisation code in a dispatch_once block if you need to ensure the initialisation is executed only once:</p>

<pre><code>- (void)commonFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  static dispatch_once_t onceToken;
  dispatch_once(&amp;onceToken, ^{
    NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], kUYLSettingsAmazingKey,
                                 nil];
    [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
  });
}

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [self commonFinishLaunchingWithOptions:launchOptions];
  return YES;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [self commonFinishLaunchingWithOptions:launchOptions];
  return YES;
}
</code></pre>

<p>If you do not care about backward compatibility with iOS 5 you can avoid this extra work and directly place your initialisation code in the appropriate app delegate method.</p>

<h3>Basic Steps to Enable State Preservation</h3>

<p>To get started with state preservation and restoration there are two basic steps that are always required:</p>

<ul>
<li>The App delegate must opt-in</li>
<li>Each view controller or view to be preserved/restored must have a restoration identifier assigned.</li>
</ul>


<p>In addition to these mandatory steps there are also a number of optional but very common steps:</p>

<ul>
<li>Create restoration classes for any view controllers that need to be recreated during a restore that are not otherwise created on App launch.</li>
<li>Implement encodeRestorableStateWithCoder: and decodeRestorableStateWithCoder: for views and view controllers that require state to be saved and restored.</li>
<li>Implement the UIDataSourceModelAssociation protocol for objects that are data sources for table and collection views to save and restore which rows are visible and which are selected.</li>
</ul>


<h3>Application Delegate Opt-in</h3>

<p>State preservation and restoration is an optional feature so you need
to have the application delegate opt-in by implementing two methods:</p>

<pre><code>- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
{
  return YES;
}

- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{
  return YES;
}
</code></pre>

<p>Most of the time you just want to return YES to indicate support for state preservation and restoration. However if you release an App upgrade where it would not make sense to restore from a previous version you can return NO from application:shouldRestoreApplicationState:. This might be the case if you have completely changed the view hierarchy for example.</p>

<h3>Restoration Identifier</h3>

<p>A restoration identifier is a string that you need to assign to any view controller or view that you want preserved and restored. During state preservation any view controllers or views in the view hierarchy that have a restoration identifier will be saved to disk.</p>

<p>The restorationIdentifier property can be set when the view controller is initialised but if you are loading the view controller from a Nib or Storyboard you can also set it there. You can choose any value you want as the identifier but you must ensure that the restoration path (the sequence of restoration identifiers down the view hierarchy from the root view controller) is unique for each object to be restored.</p>

<p>For our simple example project we can set the restoration identifiers in the Storyboard. For view controllers you can use Interface Builder to set a Storyboard ID and by selecting the option reuse the same ID for the Restoration ID:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-05-20-001.png" alt="" /></p>

<p>Restoration identifiers need to be set for the following view controllers:</p>

<ul>
<li>The Tab Bar Controller</li>
<li>Both Navigation Controllers</li>
<li>The Table View Controller and the associated UITableView</li>
<li>The Settings View Controller</li>
</ul>


<p>An easy mistake to make when using Interface Builder is to set the restoration identifier on the wrong object. For example, be sure to set the restoration identifier on the table view itself and not on the table view cell. The following screenshot of the storyboard shows the identifiers I used for each of the view controllers:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-05-20-002.png" alt="" /></p>

<h3>Finding or Creating View Controllers During Restoration</h3>

<p>During the restoration process UIKit will attempt to create or locate a reference to each view controller that is being restored. If the main user interface is loaded from a Nib file or Storyboard then it will already have been created when the application launched. In that case UIKit will locate the already created view controller instead of creating a new instance.</p>

<p>In this simple example all of the view controllers to be restored are located in the Storyboard file that is loaded when the application launches. This means we have nothing else to do as UIKit will take care of recreating the view controllers for us (we still need to restore the state of the view controllers). For view controllers that are not created as part of the normal application launch UIKit attempts the following steps:</p>

<ul>
<li>If the view controller has a restoration class (it implements the UIViewControllerRestoration protocol) then UIKit will use it to call the viewControllerWithRestorationIdentiferPath:coder: method. By implementing that method you can return an instance of the view controller.</li>
<li>If the view controller does not have a restoration class UIKit will call application:viewControllerWithRestorationIdentifierPath:coder: in the application delegate.</li>
</ul>


<p>I will save a detailed discussion of using a restoration class in a future post.</p>

<h3>Restoring State of View Controllers and their Views</h3>

<p>Once all of the view controllers we need have been created we need to restore any state they may need to properly recreate the user interface and any associated subviews they may contain. For any object where we have set a restoration identifier we have the option to save and restore state information by implementing the following two methods:</p>

<ul>
<li>encodeRestorableStateWithCoder:</li>
<li>decodeRestorableStateWithCoder:</li>
</ul>


<p>In our example App we have a view controller (UYLCountryViewController) that is used to display a view with the name of the capital city of the country selected in the root table view controller. The data model for this view controller is just an NSString property which is set when the view controller is pushed onto the navigation stack:</p>

<pre><code>@property (nonatomic, copy) NSString *capital;
</code></pre>

<p>When this view controller is restored we need to ensure that we also restore this data. In this case the encode and decode methods that we need to implement are as follows:</p>

<pre><code>- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
  [coder encodeObject:self.capital forKey:UYLKeyCapital];
  [super encodeRestorableStateWithCoder:coder];
}

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
  self.capital = [coder decodeObjectForKey:UYLKeyCapital];
  [super decodeRestorableStateWithCoder:coder];
}
</code></pre>

<p>Note that in both cases you need to call super to ensure the parent view controller gets a chance to save and restore state.</p>

<h3>Preserving Table View State</h3>

<p>For the table view showing the list of countries we want to be able save the current selection and the scroll position. Since the data source can change between launches of an application this is a little more complicated than just saving the indexPath of the selected and first visible row. Relying on the indexPath will give us wrong results if when we restore a number of rows have been deleted or added to the table.</p>

<p>What we need to do is map between the indexPath and an identifier we can use to uniquely locate data items. To do that we need to adopt the UIDataSourceModelAssociation protocol:</p>

<pre><code>@interface UYLTableViewController () &lt;UIDataSourceModelAssociation&gt;
</code></pre>

<p>This protocol has two required methods to map between an index path of an object in the table and an NSString identifier:</p>

<ul>
<li>modelIdentifierForElementAtIndexPath:inView:</li>
<li>indexPathForElementWithModelIdentifier:inView:</li>
</ul>


<p>In this simple example we can use the country name to uniquely identify an object in the table. For a Core Data backed data model a good choice would be a string representation of the managed object ID. The method used when saving the state which maps an index path to a string identifier is straightforward:</p>

<pre><code>- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view
{
  NSString *identifier = nil;
  if (indexPath &amp;&amp; view)
  {
    NSDictionary *country = [self.worldData objectAtIndex:indexPath.row];
    identifier = [country valueForKey:@"capital"];
  }
  return identifier;
}
</code></pre>

<p>The method used on restoration needs to map back to an index path for the object based on the identifier. This is a little more complicated in this case as we need to search an array of dictionaries for the matching object. Luckily we have a way to <a href="http://useyourloaf.com/blog/2010/10/19/searching-arrays-with-nspredicate-and-blocks.html">search an array using an NSPredicate and a block</a>:</p>

<pre><code>- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
  NSIndexPath *indexPath = nil;
  if (identifier &amp;&amp; view)
  {
    NSPredicate *capitalPred = [NSPredicate predicateWithFormat:@"capital == %@", identifier];
    NSInteger row = [self.worldData indexOfObjectPassingTest:
                     ^(id obj, NSUInteger idx, BOOL *stop)
                     {
                       return [capitalPred evaluateWithObject:obj];
                     }];

    if (row != NSNotFound)
    {
      indexPath = [NSIndexPath indexPathForRow:row inSection:0];
    }
  }

  // Force a reload when table view is embedded in nav controller
  // or scroll position is not restored. Uncomment following line
  // to workaround bug.
  [self.tableView reloadData];

  return indexPath;
}
</code></pre>

<p>Note that in the case that we cannot find the object because it has been deleted from the dataset we return nil. Also note that because of a bug in iOS 6 we need to force a reload of the table view or the scroll position is not restored. See this previous post about the <a href="http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller.html">table view state not being restored when embedded in a navigation controller</a> or also see <a href="https://openradar.appspot.com/13438788">rdar://13438788</a> for more details.</p>

<h3>Testing</h3>

<p>At this point we have done everything we need to save and restore state for this simple App. We can test the results using either the simulator or a device but you need to remember a key point I mentioned earlier. The state is only saved when the App is moved to the background and will be deleted if you force quit the App. The easiest way to test state restoration using the simulator is with the following procedure:</p>

<ul>
<li>Launch the App in the simulator and navigate to create the required App state.</li>
<li>Use the home button (⇧⌘H) to send the App to the background.</li>
<li>Stop the App using Xcode.</li>
</ul>


<p>At this point we have an App that is not running but has some saved background state. To test that the state is restored you can relaunch the App directly in the Simulator or by running it again from Xcode. A common mistake I find myself making when testing is to stop the App before sending it to the background.</p>

<h3>Wrapping Up</h3>

<p>This has been a long post considering that I only covered the basics but hopefully you have managed to follow along. I do think that for many simple use cases it is pretty simple to implement as UIKit really does take care of most of the work. I will try to explore some of the more advanced topics such as the use of restoration classes in a future post. In the mean time you can find the example Restorer XCode project in my <a href="https://github.com/kharrison/CodeExamples/tree/master/Restorer">GitHub CodeExamples</a> repository.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2013/05/21/state-preservation-and-restoration.html">State Preservation and Restoration</a> was originally posted 21 May 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Bug Table View State Not Restored When Embedded In Navigation Controller]]></title>
    
      <category term="Radar"/>
    
      <category term="State Restoration"/>
    
      <category term="tableviewcontroller"/>
    
    <link href="http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller.html"/>
    <updated>2013-04-07T21:42:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller</id>
    <content type="html"><![CDATA[<p><em>Sharing this bug report (<a href="https://openradar.appspot.com/13438788">rdar://13438788</a> duplicate of #12156999) for anybody attempting to get iOS 6 state preservation and restoration working for a table view embedded in a navigation controller.</em></p>

<h3>Problem Description</h3>

<h4>Summary</h4>

<p>Using iOS 6 state preservation and restoration the first visible row of a UITableView is not restored when the table view is embedded in a UINavigationController.</p>

<h4>Steps to Reproduce</h4>

<p><em>(using Xcode 4.6.1 and iOS 6.1.3)</em></p>

<ol>
<li><p>Create a new Xcode project using the iOS Single View Application template, specifying iPhone, Use Storyboards, Use Automatic Reference Counting.</p></li>
<li><p>Enable state preservation and restoration in the App delegate by implementing application:shouldSaveApplicationState: and application:shouldRestoreApplicationState:. Both methods should return YES.</p></li>
<li><p>Add a new class to the project that is a subclass of UITableViewController (without a XIB). Implement the two mandatory UITableViewDataSource delegate methods to provide a basic data source:</p>

<pre><code> - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {
   return 1000;
 }

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
   static NSString *CellIdentifier = @"BasicCell";
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
   cell.textLabel.text = [NSString stringWithFormat:@"Cell #%d",indexPath.row];
   return cell;
 }
</code></pre></li>
<li><p>Replace the storyboard contents with a single Table View Controller. Change the class of the controller to the name of the class created in step 3.</p></li>
<li><p>In the storyboard set the Table View Cell style to Basic and set the cell reuse identifier to &#8220;BasicCell&#8221; as specified in step 3.</p></li>
<li><p>Embed the table view controller in a navigation controller (Editor > Embed In > Navigation Controller).</p></li>
<li><p>Set the Storyboard ID for the navigation controller and the table view controller and select the &#8220;Use Storyboard ID&#8221; option to use the same identifier for the restortation ID. Also set the restoration ID for the table view.</p></li>
<li><p>Build and run</p></li>
<li><p>Scroll down the table view until row 50 is the first visible row. Use the home button to move the App to the background and then use Xcode to stop the App.</p></li>
<li><p>Run the app again to see the restored state.</p></li>
</ol>


<h4>Expected Results</h4>

<p>The first visible row should be row 50 which was the first visible row when the App was terminated.</p>

<h4>Actual Results</h4>

<p>The first visible row is row 0.</p>

<h4>Regression</h4>

<p>Delete the navigation controller from the storyboard and repeat the test. On restoring the app the first visible row is row 50.</p>

<h4>Notes</h4>

<p>A sample Xcode project to reproduce the problem can be found in my <a href="https://github.com/kharrison/CodeExamples/tree/master/BUG%20TableView%20State%20Restore">GitHub Code Examples repository</a>. The project contains two storyboards to demonstrate state restoration of a table
view both when it is the root view and when it is embedded in a navigation
controller:</p>

<ul>
<li><p>If the Target settings are used to set the Main Storyboad to NavStoryboard the
user interface consists of UITableView embedded in a Navigation Controller. In
this use case the table view state is not restored.</p></li>
<li><p>If the Target settings are used to set the Main Storyboard to MainStoryboard the user interface consists of a single UITableView which does have state restored as expected.</p></li>
</ul>


<h3>Workarounds</h3>

<p>Apple engineers suggested the following workaround which I can confirm resolves the issue:</p>

<p><em>Please do the following in the ViewController that owns the TableView:</em></p>

<pre><code>- (void) encodeRestorableStateWithCoder:(NSCoder *)coder {
  // Save anything relevant for our role as the TableView's DataSource
  [super encodeRestorableStateWithCoder:coder];
}

- (void) decodeRestorableStateWithCoder:(NSCoder *)coder {
  [super decodeRestorableStateWithCoder:coder];
  // Restore whatever we need as the TableView's DataSource, and then...
  [self.tableView reloadData];
}
</code></pre>

<p>I have also found that implementing a similar workaround with the UIDataSourceModelAssociation protocol methods works:</p>

<pre><code>- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view
{
  // Determine identifier for the current index path
  NSString *identifier = ....
  return identifier;
}

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
  // Determine index path for the identifier
  NSIndexPath *indexPath = ...

  // Force a reload when table view is embedded in nav controller
  // or scroll position is not restored
  [self.tableView reloadData];

  return indexPath;
}
</code></pre>

<p>The key to both workarounds is to force a reload of the table view data once the state has been restored.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller.html">Bug Table View State Not Restored When Embedded In Navigation Controller</a> was originally posted 07 Apr 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Downloading Old iOS SDK Documentation]]></title>
    
      <category term="Xcode"/>
    
    <link href="http://useyourloaf.com/blog/2013/04/05/downloading-old-ios-sdk-documentation.html"/>
    <updated>2013-04-05T16:08:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2013/04/05/downloading-old-ios-sdk-documentation</id>
    <content type="html"><![CDATA[<p><em>I recently did a clean install of Xcode 4.6.1 on a new Mac and found I was missing some of the earlier iOS 4.x and 5.x documentation sets. This post shows how to get that older documentation back should you need it.</em></p>

<h3>Xcode Documentation Sets</h3>

<p>Xcode Documentation Sets (&#8220;docsets&#8221;) are packaged as standard OS X bundles and updated via an RSS or Atom feed. It is beyond the scope of this post but you can find more details on how to integrate your own documentaion with Xcode in the Apple <a href="https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/Documentation_Sets/">Documentation Set Guide</a>.</p>

<p>A clean install of Xcode will download and install the docsets for the current versions of iOS, OS X and Xcode. For example, Xcode 4.6.1 which is the current version available in the Mac App Store at time of writing includes feed subscriptions to the docsets for iOS 6.1, OS X 10.8 and Xcode 4.6:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-04-05-001.png" alt="" /></p>

<p>The documentation for the most commonly used iOS and Mac OS X developer libraries can be downloaded and installed from the Downloads pane of the Xcode preferences (⌘,).</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-04-03-001.png" alt="" /></p>

<p>Unfortunately since in my case I have recently done a clean install on a new machine I am missing some of the earlier iOS 4.x and 5.x documentation sets.</p>

<h3>Adding Old Docsets to Xcode</h3>

<p>As long as you know the URL of the docset feed you need it is easy to add it back to Xcode. If you have access to an older install of Xcode on a different machine which has the missing docsets you can use it to find the feed URL&#8217;s. Luckily even if you cannot find the feed you need on another installation it is not too difficult to guess the URL.</p>

<p>From the Documentation tab of the Xcode Downloads preferences pane you can check the URL of a selected docset in the lower information window. In the example below I have highlighted the feed URL for the iOS 6.1 docset:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-04-05-002.png" alt="" /></p>

<p>The following URL&#8217;s cover the most common iOS docsets (I have shown them as http:// but you can also specify https:// or even feed://):</p>

<pre><code>http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone6.1.atom
http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone6.0.atom
http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone5_1.atom
http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone5_0.atom
http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone4_3.atom
http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone4_2.atom
http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone4_1.atom
</code></pre>

<p>To subscribe to a docset you need to use the small &#8220;+&#8221; button in the middle of the window (see previous screenshot). Copy and paste the required URL into the dialog and click the Add button. You should then see the new feed in the list of docsets and you can click the Install button to download it.</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-04-05-003.png" alt="" /></p>

<h3>Manually Download a docset</h3>

<p>If for some reason you want to download the docset without using Xcode you can manually fetch the feed and use it to get the direct URL to the docset archive. For example to manually retrieve the iOS 4.3 docset, first retrieve the atom feed using <code>curl</code> and grep for the link elements in the feed (note that I am using https as the http link is actually just a redirect):</p>

<pre><code>$ curl https://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone4_3.atom | grep link
    &lt;link rel="self" href="http://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone4_3.atom"&gt;&lt;/link&gt;
    &lt;link rel="enclosure" type="application/octet-stream" href="http://devimages.apple.com/docsets/20110309/com.apple.adc.documentation.AppleiOS4_3.iOSLibrary.xar" length="477703763"&gt;&lt;/link&gt;
    &lt;link rel="enclosure" type="application/octet-stream" href="http://devimages.apple.com/docsets/20110720/com.apple.adc.documentation.AppleiOS4_3.iOSLibrary.xar" length="229887175"&gt;&lt;/link&gt;
</code></pre>

<p>In this case the last update to the docset in the feed was on 2011-07-20 so we can retrieve that XML archive file:</p>

<pre><code>$ curl http://devimages.apple.com/docsets/20110720/com.apple.adc.documentation.AppleiOS4_3.iOSLibrary.xar -o AppleiOS4_3.iOSLibrary.xar
</code></pre>

<p>To get the docset file package uncompress the archive using the <code>xar</code> command:</p>

<pre><code>$ xar -xf AppleiOS4_3.iOSLibrary.xar
</code></pre>

<p>If you want to view the resulting docset package in Xcode you will need to move it to the Xcode docsets directory at the following location:</p>

<pre><code>~/Library/Developer/Shared/Documentation/DocSets
</code></pre>

<h3>Uninstall Old Docsets</h3>

<p>Searching for a class or framework in the Xcode organiser can be confusing when you have lots of old documentation installed. You can end up with at least one result from each version of the documentation which means you need to be careful that you are reading the latest version.</p>

<p>Unfortunately you cannot remove an Apple docset using the &#8216;-&#8217; button in the preferences pane. If you want to uninstall an Apple docset you can instead manually delete the file from the Xcode DocSets directory. This is usually located under <code>~/Library/Developer/Shared/Documentation/DocSets</code>. You can also check the location of a docset from the documentation tab of the Downloads pane in the Xcode preferences window. Select the documentation set you want to uninstall and look in the information area at the bottom of the window.</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-04-05-004.png" alt="" /></p>

<p>If you click on the installed location of the documentation set it will open in Finder with the doc set selected. Deleting the docset file will remove it from the system.</p>

<p>Note that Xcode does not provide a way for you to completely remove the feed subscription for an Apple docset. Once you have the deleted the documentation set the &#8220;Installed&#8221; status will change back to an &#8220;Install&#8221; button which is useful should you need to download it again in the future. It does however mean that you end up with an ever longer list of historical documentation feeds.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2013/04/05/downloading-old-ios-sdk-documentation.html">Downloading Old iOS SDK Documentation</a> was originally posted 05 Apr 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Core Data 2nd Edition by Marcus Zarra]]></title>
    
      <category term="core"/>
    
      <category term="data"/>
    
      <category term="reviews,"/>
    
    <link href="http://useyourloaf.com/blog/2013/03/07/core-data-by-marcus-zarra.html"/>
    <updated>2013-03-07T22:12:00+00:00</updated>
    <id>http://useyourloaf.com/blog/2013/03/07/core-data-by-marcus-zarra</id>
    <content type="html"><![CDATA[<p><img class="right" src="http://imagery.pragprog.com/products/301/mzcd2.jpg" width="150" height="250">
<em>There are many books on general iOS development but they often only provide brief coverage of Core Data. I was therefore pleased to see that my favourite book on the topic, <a href="http://pragprog.com/book/mzcd2/core-data">Core Data, Second Edition</a> by Marcus S. Zarra (The Pragmatic Bookshelf, January 2013) has recently received a major update.</em></p>

<h3>First Impressions</h3>

<p>The first edition of Core Data by Marcus Zarra was the book I turned to when I wanted to learn Core Data. Whilst it is still a great book it was starting to get a little dated. It was also heavily biased to using Core Data on the OS X desktop platform rather than iOS. This was not such a huge problem as many of the key concepts are valid for both platforms. However the use of Core Data for iOS was restricted to a single chapter which meant that iOS specific issues and features such as <code>NSFetchedResultsController</code> got only a brief mention.</p>

<p>The second edition has been substantially updated and the change in emphasis is evident from the change in subtitles of the two editions. The first edition was subtitled <em>Apple&#8217;s API for Persisting Data on Mac OS X</em> where for the 2nd Edition it is <em>Data Storage and Management for iOS, OS X and iCloud</em>. The growing army of iOS developers has had an impact:</p>

<blockquote><p>The largest number of Objective-C developers develop only for iOS, and therefore we will keep our focus there.</p></blockquote>

<p>It is also worth mentioning that the book covers the latest updates to the Core Data framework as shipped with iOS 6 and OS X 10.8. In fact, Marcus goes as far as to recommend not using the newest Core Data API&#8217;s if you need backward compatibility:</p>

<blockquote><p>However, iOS 5.0 (and Mac OS X 10.7) was a stumble, a misstep. It is far better to skip it and move on to iOS 6.0. But what about when your client/boss/customer requires you to be compatible with iOS 5.0? My advice is to use only the Core Data APIs that were available in iOS 4.x.</p></blockquote>

<h3>In Depth</h3>

<p>The first half of the book provides an in depth coverage of the key concepts of Core Data. The example code is for an iOS application and a whole chapter is dedicated to covering <code>NSFetchedResultsController</code> reflecting the new focus of the book.</p>

<p>The next three chapters on Core Data versioning and migration, performance tuning and threading are all essential reading. Even if you consider yourself a Core Data expert there is a lot of good practical advice here. The treatment of <em>migrations</em> covers both lightweight and heavy migrations with sufficient detail to understand why heavy migrations can be a headache. The discussion on <em>performance tuning</em> has good advice about handling binary data and also on when to denormalize data. This is a good lesson to learn if you are coming to Core Data with an SQL database background. Finally the chapter on <em>threading</em> covers how to use Core Data in a way that is thread safe.</p>

<p>This expanded and updated edition now also provides a detailed discussion of using Core Data with iCloud. This covers both the traditional Core Data stack and the newer UIManagedDocument API. Marcus does mention the problems Apple has had getting this to work reliably:</p>

<blockquote><p>Unfortunately, as has been demonstrated numerous times in the past, syncing is hard, very hard. Apple did not get it working acceptably in iOS 5.0 or OS X 10.7. It was not until iOS 6.0 and OS X 10.8 that iCloud has become truly reliable.</p></blockquote>

<p>I still do not feel confident syncing the standard Core Data stack with iCloud even with iOS 6.0. The known issue when the user turns off iCloud is covered and a number of experienced developers are still <a href="http://www.macworld.com/article/1167742/developers_dish_on_iclouds_challenges.html">reporting issues</a>. Hopefully when Apple do finally fix it Marcus will update the book with the details.</p>

<p>The second half of the book moves to using Core Data with OS X. If you are primarily an iOS developer this can still be interesting reading. Firstly because you should realise that you already know much of what is required. Secondly you can get a deeper understanding of some key technologies (if you will excuse the pun) such as KVC and KVO when used on the desktop platform.</p>

<p>The last three chapters of the book are somewhat bonus material. There is a discussion on how to integrate Core Data with Spotlight and Quick Look on the desktop. A further example of using KVC to store dynamic paramaters and an &#8220;academic&#8221; investigation on remotely accessing a Core Data repository using Bonjour. Interesting reading but not essential to understanding Core Data.</p>

<h3>Likes and Dislikes</h3>

<p>There is not much to dislike. This is one of those books that works well both for introductory and advanced audiences. If you are new to Core Data the basics are covered to get you up to speed. On the other hand if you have been using Core Data for a while you can jump straight to the chapters on migrations, performance and threading and learn something.</p>

<p>I have a preference for technical books that are written by experienced practitioners with a strong point of view. I don&#8217;t want a book that simply reformats the information in Apple&#8217;s documentation. The parts of this book that I like best are when Marcus is giving us his opinion on how to get the best from Core Data and what you should avoid. Overall a great book that just got better.</p>

<h3>Final Comments</h3>

<p>You can buy the dead-tree version of the book from the usual places but I prefer to get the ebook version direct from the <a href="http://pragprog.com/book/mzcd2/core-data">pragprog.com</a> web site. A final tip if you want more Marcus Zarra on Core Data I can also recommend the videos he has done with Scotty over at <a href="http://ideveloper.tv/">iDeveloper TV</a>.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2013/03/07/core-data-by-marcus-zarra.html">Core Data 2nd Edition by Marcus Zarra</a> was originally posted 07 Mar 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Xcode 4.6 Recommended Build Settings]]></title>
    
      <category term="LLVM"/>
    
      <category term="Xcode"/>
    
    <link href="http://useyourloaf.com/blog/2013/03/03/xcode-4-dot-6-recommended-build-settings.html"/>
    <updated>2013-03-03T15:26:00+00:00</updated>
    <id>http://useyourloaf.com/blog/2013/03/03/xcode-4-dot-6-recommended-build-settings</id>
    <content type="html"><![CDATA[<p>Xcode 4.6 introduced a number of additional compiler warnings that are enabled by default for new projects. Unfortunately the <a href="https://developer.apple.com/library/mac/#releasenotes/DeveloperTools/RN-Xcode/">release notes</a> are none too clear about the new options:</p>

<blockquote><p>LLVM: New compiler warnings to help find subtle behavioral bugs when using automatic release counting (ARC) and weak references.</p></blockquote>

<p>If you have an existing project you can update to the new recommended build settings from the project page using the &#8220;Validate Settings&#8221; button:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-02-13-001.png" alt="" /></p>

<p>A diff with the Xcode <code>project.pbxproj</code> file checked into source control reveals the changed settings:</p>

<pre><code>CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
</code></pre>

<p>If you check the build settings for the project you will find three of the new settings in the <em>Apple LLVM compiler 4.2 - Warnings - All languages</em> section:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-03-03-001.png" alt="" /></p>

<p>The remaining setting is in the <em>Apple LLVM compiler 4.2 - Warnings - Objective C</em> section:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-03-03-002.png" alt="" /></p>

<p>A useful tip here to get a detailed description for a build setting is to have the quick help window open in the utilities sidebar when clicking on each setting.</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-03-01-001.png" alt="" /></p>

<h3>New Project Build Settings</h3>

<p>For the purposes of this post I have been using one of the example projects (WorldFacts) from my <a href="https://github.com/kharrison/CodeExamples/tree/master/WorldFacts">GitHub CodeExamples</a> repository which was created back in June 2012. From the date I would guess that means I was probably using Xcode 4.3.3. Out of curiosity I compared the build settings after updating this project with a clean new project created with Xcode 4.6. There seems to be one additional compiler warning that is enabled by default for the new Xcode 4.6 project that the validate settings option does not enable for existing projects:</p>

<blockquote><p>Empty Loop Bodies: Warn about loop bodies that are suspiciously empty.   [CLANG_WARN_EMPTY_BODY, -Wempty-body]</p></blockquote>

<p>It is possible this was already a default for new projects prior to Xcode 4.6 and I have never noticed. It does seem strange though that the validate settings option does not update it for existing projects. Anyway since I would probably like to know about suspiciously empty loop bodies I have also enabled it for the existing project.</p>

<p><em>What follows is a more detailed description of each of the four new Xcode 4.6 compiler warning build settings. In each case I have included the detailed description from the help documentation for reference.</em></p>

<h3>Implicit Constant Conversions</h3>

<p><em>Warn about implicit conversions of constant values that cause the constant value to change, either through a loss of precision, or entirely in its meaning.  [CLANG_WARN_CONSTANT_CONVERSION, -Wconstant-conversion]</em></p>

<p>This catches problems such as the following where a constant is converted to a type that causes the value to change:</p>

<pre><code>int8_t smallInt = 500;
Implicit conversion from 'int' to 'int8_t' (aka 'signed char') changes value from 500 to -12

NSInteger value = 4294967296;
Implicit conversion from 'long long' to 'NSInteger' (aka 'int') changes value from 4294967296 to 0
</code></pre>

<h3>Implicit Enum Conversions</h3>

<p><em>Warn about implicit conversions between different kinds of enum values.  For example, this can catch issues when using the wrong enum flag as an argument to a function or method.  [CLANG_WARN_ENUM_CONVERSION, -Wenum-conversion]</em></p>

<p>For an example, suppose I have two somewhat similar enum types defined for a class:</p>

<pre><code>typedef enum
{
  UYLMagicUser = 0,
  UYLMagicAdmin = 1
} UYLMagicValue;

typedef enum
{
  UYLNonMagicUser = 10,
  UYLNonMagicAdmin = 11
} UYLNonMagicValue;
</code></pre>

<p>A method that is expecting a UYLMagicValue as an argument:</p>

<pre><code>- (void)doSomeMagic:(UYLMagicValue)magicType
{
  //
}
</code></pre>

<p>Most of the time Xcode autocompletion will guide you to the right value when calling this method but it is still easy to end up with the following by mistake:</p>

<pre><code>[self doSomeMagic:UYLNonMagicAdmin];
</code></pre>

<p>Assuming that I had actually intended to pass UYLMagicAdmin this is going to end in disappointment. With the new compiler warning enabled  you get the following:</p>

<pre><code>Implicit conversion from enumeration type 'UYLNonMagicValue' to different enumeration type 'UYLMagicValue'
</code></pre>

<h3>Incompatible Integer to Pointer Conversion</h3>

<p><em>Warn about implicit conversions between pointers and integers.  For example, this can catch issues when one incorrectly intermixes using NSNumber&#8217;s and raw integers.  [CLANG_WARN_INT_CONVERSION, -Wint-conversion]</em></p>

<p>This warning works either way when there is an implicit conversion between integers and pointers:</p>

<pre><code>char smallInt = @"1";
Incompatible pointer to integer conversion initializing 'char' with an expression of type 'NSString *'

char *pointer = 1234;
Incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int'
</code></pre>

<h3>Duplicate Method Definitions</h3>

<p><em>Warn about declaring the same method more than once within the same @interface.</em></p>

<p>This is a pretty simple one that picks up multiple definitions of the same method in an interface definition:</p>

<pre><code>@interface UYLMyClass ()
- (void)someRandomMethod:(NSString *)name;
// Lots of other stuff...
// and more...
- (void)someRandomMethod:(NSString *)name;
@end
Multiple declarations of method 'someRandomMethod:' found and ignored
</code></pre>

<h3>One last thing</h3>

<p>If you are still using the LLVM-GCC compiler or GDB debugger you should also note the following warning in the Xcode 4.6 release notes and start thinking about adopting LLVM/LLDB in the near future:</p>

<blockquote><p>DEPRECATED: LLVM-GCC compiler and GDB debugger.
Xcode 4.6 is the last release to include the LLVM-GCC compiler and the GDB debugger.</p>

<p>Use the LLVM compiler and the LLDB debugger, and file reports at https://bugreport.apple.com for issues that require the use of LLVM-GCC or GDB.</p></blockquote>

      <hr><p><a href="http://useyourloaf.com/blog/2013/03/03/xcode-4-dot-6-recommended-build-settings.html">Xcode 4.6 Recommended Build Settings</a> was originally posted 03 Mar 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Apple Webpage Touch Icons]]></title>
    
      <category term="HTML"/>
    
      <category term="Safari,"/>
    
    <link href="http://useyourloaf.com/blog/2013/02/23/apple-webpage-icons.html"/>
    <updated>2013-02-23T22:32:00+00:00</updated>
    <id>http://useyourloaf.com/blog/2013/02/23/apple-webpage-icons</id>
    <content type="html"><![CDATA[<p>Mobile Safari allows you to add an icon to the home screen of a device for any web page you visit using the share button. The screen shot below shows the icon that is used if you do this for apple.com.</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-02-24-001.png" alt="Add to Home Screen" /></p>

<p>If your website does not supply an icon it will use a screenshot of the page which will often look less then impressive. You will also see a lot of failed requests for the file <code>apple-touch-icon.png</code> in the error logs for the web site which can be annoying. If you have a web site that you expect to be visited by users with an Apple device (which I guess is most sites) you should probably spend a few minutes to make that icon look good on the users device.</p>

<h3>Webpage Touch Icons</h3>

<p>The ever growing range of Apple devices with different form factors and screen resolutions makes keeping track of the various icon files you need no easy task. At the time of writing the list of icons file sizes for each device type is as follows:</p>

<ul>
<li>apple-touch-icon.png (57x57 iPhone and iPod touch)</li>
<li>apple-touch-icon-72x72.png (72x72 iPad 1st and 2nd gen)</li>
<li>apple-touch-icon-114x114.png (114x114 retina iPhone and iPod touch)</li>
<li>apple-touch-icon-144x144.png (144x144 retina iPad)</li>
</ul>


<p>The filenames listed above are the default names you should use if you are relying on Safari to find the icon files in your website root directory.</p>

<p>The icon with the most appropriate size for the device will be used if present. The rules for which icon will be used in cases where the preferred size is not available are a little complicated. In theory the next largest is used if present or failing that the largest icon is used. This means that you could just create a single icon of 144x144 pixels and it will be downloaded and resized by the browser as required. However this is a little wasteful given that it does not take much effort to just create each of the icon sizes I listed previously.</p>

<p>By default Safari will also add rounded corners and a glossy shine effect to the icon similar to the way application icons are treated. The ability to specify a precomposed image which will not be modified was introduced in iOS 2.0. If you do not want Safari to mess with the image you can add &#8220;precomposed&#8221; to the filename (e.g. <code>apple-touch-icon-precomposed.png</code>). If you supply both a normal and precomposed version of an icon Safari will use the precomposed version.</p>

<h3>Webpage Touch Icon Links</h3>

<p>Rather than relying on Safari searching the root directory of a site you can also explicitly specify the icon files to use in a link element added to the head section of the web page. This can also be useful if you need to name the files differently from the default names or if you want different icons to be used for different pages within a site.</p>

<p>Using the same filenames as before a full set of links would look as follows:</p>

<pre><code>&lt;link rel="apple-touch-icon" sizes="144x144" href="http://useyourloaf.com/apple-touch-icon-144x144.png" /&gt;
&lt;link rel="apple-touch-icon" sizes="114x114" href="http://useyourloaf.com/apple-touch-icon-114x114.png" /&gt;
&lt;link rel="apple-touch-icon" sizes="72x72" href="http://useyourloaf.com/apple-touch-icon-72x72.png" /&gt;
&lt;link rel="apple-touch-icon" href="http://useyourloaf.com/apple-touch-icon.png" /&gt;
</code></pre>

<p>For completeness if you do not want Safari to add any image effects the links would be as follows:</p>

<pre><code>&lt;link rel="apple-touch-icon-precomposed" sizes="144x144" href="http://useyourloaf.com/apple-touch-icon-144x144-precomposed.png" /&gt;
&lt;link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://useyourloaf.com/apple-touch-icon-114x114-precomposed.png" /&gt;
&lt;link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://useyourloaf.com/apple-touch-icon-72x72-precomposed.png" /&gt;
&lt;link rel="apple-touch-icon-precomposed" href="http://useyourloaf.com/apple-touch-icon-precomposed.png" /&gt;
</code></pre>

<h3>Browser Compatibility</h3>

<p>The situation gets a little more complicated if you care about supporting older versions of iOS or other mobile browser platforms (e.g. Android, Blackberry, Microsoft). For Safari the only real issue is if you need to support devices running anything earlier than iOS 4.2 which do not support specifying icons with different sizes. For that situation it is a good idea to always include <code>apple-touch-icon-precomposed.png</code> and <code>apple-touch-icon.png</code> files as a fallback.</p>

<p>Other browsers have varying levels of support for the Apple way of doing things.
For more on cross-browser compatibility issues and recommendations see this <a href="http://mathiasbynens.be/notes/touch-icons">excellent article</a>. Some general guidelines that I end up with:</p>

<ul>
<li>Always use the Apple defined names rather than custom names.</li>
<li>Always place the icon files in the document root if possible.</li>
<li><p>I prefer the precomposed variation but also include <code>apple-touch-icon.png</code> as a fallback. For example, this site has the following icon files in the document root:</p>

<pre><code>apple-touch-icon-72x72-precomposed.png
apple-touch-icon-114x114-precomposed.png
apple-touch-icon-144x144-precomposed.png
apple-touch-icon-precomposed.png
apple-touch-icon.png
</code></pre></li>
<li><p>Include the link elements in the page head section in addition to having the files in the standard location.</p></li>
</ul>


      <hr><p><a href="http://useyourloaf.com/blog/2013/02/23/apple-webpage-icons.html">Apple Webpage Touch Icons</a> was originally posted 23 Feb 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Open With Menu Duplicates]]></title>
    
      <category term="osx"/>
    
    <link href="http://useyourloaf.com/blog/2013/01/01/open-with-duplicates.html"/>
    <updated>2013-01-01T12:24:00+00:00</updated>
    <id>http://useyourloaf.com/blog/2013/01/01/open-with-duplicates</id>
    <content type="html"><![CDATA[<p>I have for some time been suffering a minor (but it seems not uncommon) annoyance with the &#8220;Open With&#8221; menu when I right click on a document in the Finder. Over time a number of old and duplicate items have worked there way into the list. It seems that OS X has at some point spotted additional copies of applications and helpfully added them to the menu. VMWare Fusion has also made a contribution adding some applications from an old Windows XP image before I figured out how to disable that option. The following is what I was seeing when I right-clicked on a <code>pdf</code> file:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-01-01-001.png" alt="duplicate open with" /></p>

<p>Now I like Pixelmator and Evernote but there is no way I really want to see them listed five times and I have never wanted to open a pdf using Internet Explorer. I cannot say for sure when I first noticed this problem but I do know it is worse since I upgraded to Mountain Lion.</p>

<h3>Launch Services</h3>

<p>The Launch Services API is what controls how a running application can open a document in another application. When you open a file in the Finder what actually happens under the covers is that the Finder uses the Launch Services API to request that the associated application is used to open the file on behalf of the user.</p>

<p>In order to be able to respond to such requests Launch Services maintains a database in which it records all registered applications and the kinds of documents each application can open. (If you are curious you can find this database in <code>~/Library/Preferences/com.apple.LaunchServices.plist</code>.) The system takes care of registering applications with Launch Services automatically in the following situations:</p>

<ul>
<li>When the system boots or a new user logs in the Applications directory is scanned and any new applications are registered.</li>
<li>The Finder will automatically register any new applications as it &#8220;becomes aware of them&#8221; such as when they are installed.</li>
<li>When the user opens a document which does not have a preferred application registered in the launch services database they will be asked to select one by the Finder which is then registered for future use.</li>
</ul>


<p>Luckily you do not really need to know anything about Launch Services to clean up the &#8220;Open With&#8221; menu.</p>

<h3>Command-Line Utility - lsregister</h3>

<p>The easiest way to interact with the launch services database is to use the <code>lsregister</code> command-line utility from the terminal. Unfortunately it is buried deep down in a system library subdirectory:</p>

<pre><code>$ cd /System/Library/Frameworks/CoreServices.framework/Versions/Current/Frameworks/LaunchServices.framework/Versions/Current/Support/
</code></pre>

<p>You can of course just search from the command-line if you are having problems finding it on older versions of OS X:</p>

<pre><code>$ find /System/Library/Frameworks -name lsregister
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister
</code></pre>

<p>The two directory paths although slightly different are actually equivalent as the <code>Current</code> directory is actually just a link to the <code>A</code> directory. Whichever path you use once you have set it as your current working directory you can reset the database with the following command:</p>

<pre><code>$ ./lsregister -kill -r -all system,local,user
</code></pre>

<p>Notes:</p>

<ul>
<li><p>The above commands were tested on OS X Mountain Lion (v10.8.2), earlier OS versions stored the lsregister command in different locations and used different command-line options (see below).</p></li>
<li><p>If you google for &#8220;lsregister&#8221; or for &#8220;Open With Duplicates&#8221; you will find that most people will recommend the following command to reset the launch services database.</p>

<pre><code>$ ./lsregister -kill -r -domain system -domain local -domain user
</code></pre>

<p>As far as I can tell the two command-line variations are equivalent and do the same thing. The latter of the two (using -domain) no longer appears as a valid command-line option (use ./lsregister -h to see all options) but still works as of Mountain Lion (v10.8.2). If you running an earlier version of OS X you may need to use this variation.</p></li>
<li><p>I did not find it necessary to restart the Finder or reboot for the changes to take effect but your mileage may indeed vary.</p></li>
<li><p>If you add the -v option for verbose output to the above lsregister command you can watch as the system library and application directories are scanned and each application is registered. Do not be alarmed by the -10811 error messages, they are just indicating that a non-application file or directory was found and could not be registered which is harmless.</p>

<pre><code>  ...
  lsregister: registered /Applications/Twitterrific.app
  lsregister: error -10811 registering /Applications/Utilities
  lsregister: error -10811 registering /Applications/Utilities/.DS_Store
  lsregister: error -10811 registering /Applications/Utilities/.localized
  lsregister: registered /Applications/Utilities/Activity Monitor.app
  ...
</code></pre></li>
</ul>


<h3>Finally Back To Normal</h3>

<p>After resetting the launch services database my &#8220;Open With&#8221; menu is finally back to a clean and useful size. The following is what I now see for a <code>pdf</code> file:</p>

<p><img src="http://useyourloaf.com/assets/images/2013/2013-01-01-002.png" alt="clean open with" /></p>

<p>Several days later my menu is still looking clean so I am hoping it will now stay that way. Unfortunately it seems that this is a long standing OS X problem even though it only seems to have recently started to annoy me.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2013/01/01/open-with-duplicates.html">Open With Menu Duplicates</a> was originally posted 01 Jan 2013 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Supporting the 4-inch Retina Display]]></title>
    
      <category term="retina"/>
    
    <link href="http://useyourloaf.com/blog/2012/12/31/retina-4-support.html"/>
    <updated>2012-12-31T15:10:00+00:00</updated>
    <id>http://useyourloaf.com/blog/2012/12/31/retina-4-support</id>
    <content type="html"><![CDATA[<p>It already seems a long time ago that the iPhone 5 and iPod touch (5th generation) devices were released with the 4-inch retina display. Better late than never I finally get around in this post to sharing my notes on the often minimal changes required to support the new screen dimensions.</p>

<h3>Letterbox Mode</h3>

<p>If you make no modifications to an existing app it will still work on the new devices but displays in a letterbox with black bars at the top and bottom of the app. The following screenshots show an unmodified version of my <a href="https://github.com/kharrison/CodeExamples/tree/master/WorldFacts">World Facts example app</a> in both portrait and landscape orientations running on the larger 4-inch device (in this case a 5th gen iPod touch):</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-12-30-001.png" alt="letterbox portrait" />
<img src="http://useyourloaf.com/assets/images/2012/2012-12-30-002.png" alt="letterbox landscape" /></p>

<p>The sinking feeling I get when I see an App displaying in letterbox mode reminds me of when the iPad launched and many apps would only run in 2x mode.</p>

<h3>Retina 4 Launch images</h3>

<p>If you have an app using standard view controllers without any custom drawing or artwork it turns out there is very little you need to do to support the new screen dimensions other than add a new launch image. The iOS Human Interface Guidelines give the required dimensions to use:</p>

<blockquote><p>For apps that run on iPhone 5 and iPod touch (5th generation), create a launch image that measures 640 x 1136 pixels.</p></blockquote>

<p>You can also find details in the iOS App Programming Guide include the naming convention for the default filename:</p>

<blockquote><p>To specify default launch images for iPhone 5 and iPod touch (5th generation) devices, include the modifier string -568h immediately after the <basename> portion of the filename. Because these devices have Retina displays, the @2x modifier must always be included with launch images for the devices.</p></blockquote>

<p>If you open an existing app in a recent version of Xcode (4.5.2 at time of writing) you will get a build issue that also shows you the required filename:</p>

<pre><code>Retina 4 Support: Missing "Default-568h@2x.png" launch image.
</code></pre>

<p>Clicking on the issue in the navigator will display a dialog with Xcode offering to add the missing launch image for you:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/missingretina4launchimage.png" alt="missing retina 4 launch image" /></p>

<p>If you accept and allow Xcode to add the missing launch image it will add a file named <code>Default-586h@2x.png</code> to the project with dimensions of 640 x 1136 pixels. This will work but the image that is added to the project is a plain black background which does not match our initial user interface very well. Since I never previously bothered to add any launch images (or icons) to this example app I will add three of my own launch images as follows:</p>

<ul>
<li>Default.png - 320 x 480 pixels (standard resolution iPhone)</li>
<li>Default@2x.png - 640 x 960 pixels (high resolution iPhone 4)</li>
<li>Default-568h@2x.png - 640 x 1136 pixels (iPhone 5)</li>
</ul>


<p>The launch image consists of a 20 pixel high (40 pixel for high resolution) status bar, a 44 pixel high title bar (88 pixel for high resolution) and then a white content area. Since this is an iPhone only app we do not need to worry about iPad or landscape launch images. Once added to Xcode the three launch images should show up in the target summary screen of the project (if you prefer you can just drap and drop the images onto the relevant placeholder to have Xcode add the files to the project for you):</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-12-31-001.png" alt="xcode launch image" /></p>

<p>With the correct launch image in place the application should now make full use of the larger 4-inch screen:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-12-31-002.png" alt="screenshot" /></p>

<h3>Auto-sizing</h3>

<p>One issue that can cause problems on the larger 4-inch screen is that a view may not correctly resize to the taller screen size. Assuming you have not yet migrated to auto-layout the auto-sizing springs and struts must be set correctly to allow each view to grow in height.</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-12-31-003.png" alt="autosizing" /></p>

<p>This is something that is easy to overlook when testing so be sure to check each view on an actual device. In this case I already had the main table view set correctly to fill the content area so everything just worked.</p>

<h3>Wrapping up</h3>

<p>As the iOS device family grows so does the list of image assets and resources required. Whilst it will not be so simple for all apps in this case supporting the 4-inch retina display only required adding one new launch image. What continues to be important is to thoroughly test on a real device.</p>

<p>The modified example Xcode project that accompanies this post can be found in my GitHub <a href="https://github.com/kharrison/CodeExamples/tree/master/WorldFacts">Code Examples repository</a>. Since I am posting this on the last day of 2012 I will also take the opportunity to wish you all a happy new year!</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/12/31/retina-4-support.html">Supporting the 4-inch Retina Display</a> was originally posted 31 Dec 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Presenting View Controllers]]></title>
    
      <category term="viewController"/>
    
    <link href="http://useyourloaf.com/blog/2012/10/08/presenting-view-controllers.html"/>
    <updated>2012-10-08T21:01:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/10/08/presenting-view-controllers</id>
    <content type="html"><![CDATA[<p>It has been a long time since I posted about about <a href="http://useyourloaf.com/blog/2010/05/03/ipad-modal-view-controllers.html">iPad Modal View Controllers</a>. The last couple of years has seen the introduction first of iOS 5 and storyboards and now iOS 6. This has in turn seen the old methods for presenting and dismissing modal views controllers discouraged and now formally deprecated. So I think it is time for a quick update on what has changed and how to migrate old code.</p>

<h3>Modal The Old Fashioned Way</h3>

<p>In the good old days of iOS 3.2 and iOS 4 if you wanted to create a modal view controller you would do so with code that looked something like this:</p>

<pre><code>DetailViewController *viewController = [[DetailViewController alloc]
                                       initWithNibName:@"DetailViewController"
                                                bundle:nil];
viewController.delegate = self;
UINavigationController *navController = [[UINavigationController alloc]
                                        initWithRootViewController:viewController];
[self presentModalViewController:navController animated:YES];
</code></pre>

<p>This code fragment is taking from the old iOS 3.2 era post on <a href="http://useyourloaf.com/blog/2010/05/03/ipad-modal-view-controllers.html">iPad Modal View Controllers</a> but is fairly typical. The user interface XIB file is first created by Interface Builder and then used to instantiate the new view controller.</p>

<p>In this example the view controller is embedded in a navigation controller but the key to presenting the modal view controller is the call to presentModalViewController:animated:. A similar call to dismissModalViewControllerAnimated: in the presenting view controller takes care of removing the modal view controller.</p>

<p>The modalPresentationStyle property controls whether the view controller is presented full screen, as a page or form sheet on the iPad. Likewise the modalTransitionStyle property controls how the new view animates onscreen.</p>

<h3>Presented and Presenting View Controllers</h3>

<p>With iOS 5 Apple started to deprecate the modal view controller methods and replace them with the more general concept of presenting and presented view controllers. The modal view controller being the presented view controller. Conceptually not much has changed and if you adopt storyboards it gets even easier. Consider a trivial two view controller application represented by the following storyboard:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-10-08-001.png" alt="storyboard" /></p>

<p>The root view contains three buttons each of which is wired to trigger a different modal segue to the presented view controller. The three segues have unique identifiers and specify both the modal presentation and transition styles in the storyboard. For example here is the storyboard segue for the full screen button:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-10-08-002.png" alt="full screen segue" /></p>

<p>The page sheet segue which is full screen height but uses the portrait screen width when in landscape is specified as follows:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-10-08-003.png" alt="page sheet segue" /></p>

<p>Finally the form sheet segue which uses both a view height and width smaller than full screen is specified as follows:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-10-08-004.png" alt="form sheet segue" /></p>

<p>If you are not using storyboards and creating a separate NIB file for the presented view controller you will need to implement a method for the various UIButton actions that creates and presents the new controller manually. For example, the method triggered when the full screen button is tapped would look something like this:</p>

<pre><code>- (IBAction)selectedFullScreen:(UIButton *)sender
{
  UYLPresentedViewController *viewController = [[UYLPresentedViewController alloc]
                                               initWithNibName:@"UYLPresentedViewController"
                                                        bundle:nil];
  viewController.delegate = self;
  viewController.modalPresentationStyle = UIModalPresentationFullScreen;
  [self presentViewController:viewController animated:YES completion:NULL];
}
</code></pre>

<p>Note the call to presentViewController:animated:completion:. The completion argument can take a block which is called after the viewDidAppear: method of the presented view controller. Specify NULL if you do not need the completion handler.</p>

<h3>Dismissing Presented View Controllers</h3>

<p>Not much has changed when it comes to dismissing modal view controllers other than the name of the method you should use. Best practise suggests that you arrange for the presenting view controller to dismiss the presented view controller which generally means setting up a delegate protocol. This is nothing new but for completeness I will show a typical interface for a presented view controller:</p>

<pre><code>@protocol UYLPresentedViewControllerDelegate &lt;NSObject&gt;
- (void)didDismissPresentedViewController;
@end

@interface UYLPresentedViewController : UIViewController
@property (nonatomic, weak) id&lt;UYLPresentedViewControllerDelegate&gt; delegate;
@end
</code></pre>

<p>The UYLPresentedViewController class defines a protocol that we expect all users of the class to adopt. It has a single mandatory method that will be called when we determine that the presented view controller will be dismissed. If you need to pass data back to the presenting view controller you could add an argument to this method. The public interface definition of the class includes a weak reference to the delegate.</p>

<p>The done button in the presented view controller is then wired to call the following action method when it is touched:</p>

<pre><code>- (IBAction)didSelectDone:(UIButton *)sender
{
  [self.delegate didDismissPresentedViewController];
}
</code></pre>

<p>The presenting view controller needs to adopt the protocol:</p>

<pre><code>@interface UYLViewController : UIViewController &lt;UYLPresentedViewControllerDelegate&gt;
</code></pre>

<p>It also needs to set itself as the delegate which is not something we can do directly in the storyboard. Instead we need to implement prepareForSegue:sender: as follows to retrieve the newly instantiated view controller and set the delegate:</p>

<pre><code>- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  if ([segue.identifier isEqualToString:UYLSegueFullScreen] ||
      [segue.identifier isEqualToString:UYLSeguePageSheet] ||
      [segue.identifier isEqualToString:UYLSegueFormSheet])
  {
    UYLPresentedViewController *viewController = segue.destinationViewController;
    viewController.delegate = self;
  }
}
</code></pre>

<p>With the delegate set we can complete the implementation of didDismissPresentedViewController.</p>

<pre><code>- (void)didDismissPresentedViewController
{
  [self dismissViewControllerAnimated:YES completion:NULL];
}
</code></pre>

<p>Note that we now call dismissViewControllerAnimated:completion: instead of dismissModalViewControllerAnimated:. The completion handler in this case if specified is called after the viewDidDisappear: method is called on the presented view controller.</p>

<p>If defining the delegate protocol seems like a lot of work for such a trivial example you can take a short cut. The UIViewController class now has two properties to indicate both the presentedViewController and the presentingViewController. We could use this to dismiss the view controller directly from the presented view controller. For example we could change our UIButton action method to the following:</p>

<pre><code>- (IBAction)didSelectDone:(UIButton *)sender
{
  [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
}
</code></pre>

<p>This achieves the same effect without the need to define and set a delegate but in general I prefer the fuller approach of keeping the presentation and dismissal all in the presenting view controller. The use of delegation also makes it easier when you need to pass data back to the presenting view controller.</p>

<h3>Migration</h3>

<p>As of the time of writing this post the presentModalViewController:animated: and dismissModalViewControllerAnimated: methods do still exist in iOS 6 but are deprecated and will generate Xcode compilation warnings. If you are starting a new project today and you can target iOS 5 or later you should just use the new methods. Likewise if you have an existing app that uses the deprecated methods now is a good time to think about updating assuming you no longer require iOS 4.</p>

<p>If you have already made the switch to using storyboards for the user interface you may find that you have already eliminated the calls to presentModalViewController:animated:. As I showed above the storyboard takes care of instantiating and presenting the view controller for you.</p>

<p>However since with storyboards you still need to take care of dismissing the view controller you may have some calls to dismissModalViewControllerAnimated: buried in your view controller code. The migration in this case is trivial since you can generally replace these with dismissViewControllerAnimated: as I described above.</p>

<h4>Updated: 10-Oct-2012</h4>

<p>As was pointed out in the comments the code as originally posted for dismissing the presented (modal) view controller from within the presented view controller contained a mistake. The dismissViewControllerAnimated:completion: method should of course be called on self.presentingViewController. A further comment pointed out some unnecessary code in the didSelectDone method that was checking the value of self.delegate which is unnecessary since a method call on nil is harmless. The code snippets in the post have been updated accordingly.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/10/08/presenting-view-controllers.html">Presenting View Controllers</a> was originally posted 08 Oct 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[VoiceOver Bug and iOS 5 TableViews Revisited]]></title>
    
      <category term="VoiceOver"/>
    
      <category term="iOS 5"/>
    
      <category term="tableviewcontroller"/>
    
    <link href="http://useyourloaf.com/blog/2012/09/11/voiceover-bug-and-ios-5-tableviews-revisited.html"/>
    <updated>2012-09-11T19:18:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/09/11/voiceover-bug-and-ios-5-tableviews-revisited</id>
    <content type="html"><![CDATA[<p>Unfortunately I need to revisit the previous post about an iOS 5 bug that was preventing <a href="http://useyourloaf.com/blog/2012/09/07/prototype-table-view-cells-not-working-with-voiceover.html">prototype table view cells working with VoiceOver</a>. After posting I realised I had not quite done enough to work around the problem when using storyboards.</p>

<h3>The Problem</h3>

<p>In a nutshell there is a known bug in iOS 5 when VoiceOver is active which causes calls to the <code>UITableView</code> method <code>dequeueReusableCellWithIdentifier:</code> to fail to return a table view cell. I experienced this bug when playing with prototype cells created by a storyboard but I should be clear that the bug is not directly related to either storyboards or prototype cells (though it does have some extra impact for storyboards). You can experience the problem even if you not using storyboards and simply using a standard UITableView cell style:</p>

<pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *CellIdentifier = @"SubtitleCell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil)
  {
    NSLog(@"Failed to dequeue cell");
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                  reuseIdentifier:CellIdentifier];
  }
  // configure cell
  return cell;
}
</code></pre>

<p>With VoiceOver active on an iOS 5 device the above code will <em>always</em> fail to dequeue a cell and fall through to the cell allocation code (logging &#8220;Failed to dequeue cell&#8221;). Of course if you have registered a NIB with the table view you may be surprised when you do not get back a cell and crash. Hence my original workaround which was to always test that a cell is returned and manually allocate when VoiceOver is active.</p>

<h3>Everlasting Cells</h3>

<p>One of the impacts of this bug is that when VoiceOver is active table view cells never get reused. This means that as the table view is scrolled new cells are constantly being allocated. This is clearly visible in Instruments if you scroll
a table view whilst running on an iOS 5 device with VoiceOver active. If you have very large table view cells and do lots and lots of scrolling you could in theory run out of memory. In practise I would guess that table view cells are small enough that normal table view activity is not sufficient to cause a serious problem.</p>

<h3>Broken Seques</h3>

<p>There is one other impact of this bug when using Storyboards that I missed when first attempting a workaround in my example storyboard app, WorldFacts. My initial attempt was simply to load the custom country cell from a separate XIB file using UINib method <code>instantiateWithOwner:options:</code>. This appeared to work but unfortunately since this new cell was not loaded via the storyboard it is not associated with any of the segues defined in the storyboard. This means that tapping a row in the table with VoiceOver active does nothing. The seque to the detailed country view controller is never triggered.</p>

<p>I think the reason I did not immediately spot this problem is that it does not occur if you activate VoiceOver when the table view cells have already been created from the storyboard. The easiest way to reproduce the problem is to ensure that VoiceOver is active before the App is launched.</p>

<h3>Manually Triggering A Segue</h3>

<p>To trigger the segue for the cells we have created with VoiceOver active we could just simply perform the required segue with <code>performSegueWithIdentifier:sender:</code> in the table view delegate method <code>tableView:didSelectRowAtIndexPath:</code>. However we need to be careful not to manually trigger the segue for normally created cells as the storyboard will also perform the segue for those cells.</p>

<p>To avoid triggering the seque twice I ended up using a different cell identifier for the cells that I am manually creating when VoiceOver is active. So my final implementation of <code>tableView:cellForRowAtIndexPath:</code> starts as follows:</p>

<pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:UYLCountryCellIdentifier];
</code></pre>

<p>This is the original cell creation using the cell identifier (<code>UYLCountryCellIdentifier</code>) for the prototype cell registered in the storyboard. In normal conditions this will always return a cell but with VoiceOver active on iOS 5 it returns nil.</p>

<pre><code>  if (cell == nil)
  {
    cell = [self.tableView dequeueReusableCellWithIdentifier:UYLNibCountryCellIdentifier];

    if (cell == nil)
    {
        [self.countryCellNib instantiateWithOwner:self options:nil];
        cell = self.countryCell;
        self.countryCell = nil;
    }
  }
</code></pre>

<p>When I fail to get a cell from the storyboard I then attempt to dequeue a cell with the identifier (<code>UYLNibCountryCellIdentifier</code>) of the cell in the registered XIB file. This is of course futile since with VoiceOver active it will also fail. Finally I instantiate a new cell using the cached UINib object (refer to the previous post for further details).</p>

<p>Once we have identified our manually created cells we can implement the table view delegate method <code>tableView:didSelectRowAtIndexPath:</code> to manually trigger the segue to the detailed view for just these cells:</p>

<pre><code>- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
  if ([cell.reuseIdentifier isEqualToString:UYLNibCountryCellIdentifier])
  {
    [self performSegueWithIdentifier:UYLSegueShowCountry sender:cell];
  }
}
</code></pre>

<p>Note that once we have called <code>performSequeWithIdentifier:sender:</code> for our manually allocated cell we end up back at the <code>prepareForSegue:sender:</code> method as for a correctly created cell and the view transition completes.</p>

<h3>All Done</h3>

<p>I hope that really is everything now to workaround this annoying bug when using storyboards. Unfortunately even with the imminent release of iOS 6 it seems likely that we will have to live with this bug for as long as iOS 5 support is required. See my <a href="https://github.com/kharrison/CodeExamples">GitHub CodeExamples</a> repository for the updated <a href="https://github.com/kharrison/CodeExamples/tree/master/WorldFacts">WorldFacts App</a>.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/09/11/voiceover-bug-and-ios-5-tableviews-revisited.html">VoiceOver Bug and iOS 5 TableViews Revisited</a> was originally posted 11 Sep 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Prototype Table View Cells Not Working With VoiceOver]]></title>
    
      <category term="VoiceOver"/>
    
      <category term="accessibility"/>
    
      <category term="storyboard"/>
    
      <category term="tableviewcontroller"/>
    
    <link href="http://useyourloaf.com/blog/2012/09/07/prototype-table-view-cells-not-working-with-voiceover.html"/>
    <updated>2012-09-07T16:20:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/09/07/prototype-table-view-cells-not-working-with-voiceover</id>
    <content type="html"><![CDATA[<p><em>Just when I thought I had learnt everything there was to know about storyboards I hit another bug today when using VoiceOver on iOS 5.</em></p>

<h3>VoiceOver And Out</h3>

<p>The problem is easily reproducible using the WorldFacts example app that I first used to examine <a href="http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html">prototype cells and storyboards</a>. Unfortunately when running on a device with iOS 5.1.1 with VoiceOver turned on the application crashes as follows:</p>

<pre><code>*** Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit/UIKit-1914.85/UITableView.m:6061
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
</code></pre>

<p><em>Note that you must be running on a device, not the simulator, to reproduce the problem.</em></p>

<p>For anybody who made it through my post yesterday on <a href="http://useyourloaf.com/blog/2012/09/06/search-bar-table-view-storyboard.html">adding a search bar</a> to the project this should look familiar. The problem is with the same line of code in <code>tableView:cellForRowAtIndexPath:</code> that is supposedly guaranteed to create or dequeue a table view cell using the prototype cell from the storyboard:</p>

<pre><code>UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:UYLCountryCellIdentifier];
</code></pre>

<p>Yesterday the problem was caused by the search results controller creating a new table view that is not associated with our prototype cell. The not too great workaround of using self.tableView to retrieve the cell saved the day even if it makes me uncomfortable.</p>

<p>Today the problem seems to be that VoiceOver or more probably the UIAccessibility API is interfering with the loading of the prototype cell. I cannot see an easy workaround for this other than creating the custom cell in a separate XIB file and loading it manually the old-fashioned way.</p>

<p>Note that the problem does not occur for <a href="http://useyourloaf.com/blog/2012/05/07/static-table-views-with-storyboards.html">static table view cells</a>.</p>

<h3>Fallback To UINib</h3>

<p>Since I first created this app with a manually loaded custom table view cell it is not too difficult to add back the old code. For full details you can refer to the <a href="http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html">original post</a>. In essence we need to create the custom table view cell in a separate NIB file and connect it to an outlet in our table view controller. We can lazily instantiate a UINib property to cache the table view cell:</p>

<pre><code>- (UINib *)countryCellNib
{
  if (!_countryCellNib)
  {
    _countryCellNib = [UINib nibWithNibName:@"CountryCell" bundle:nil];
  }
  return _countryCellNib;
}
</code></pre>

<p>We can now use the UINib object to create a new cell anytime dequeueReusableCellWithIdentifier fails to return a cell. The relevant code in the tableView:cellForRowAtIndexPath: method is now as follows:</p>

<pre><code>UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:UYLCountryCellIdentifier];

if (cell == nil)
{
  [self.countryCellNib instantiateWithOwner:self options:nil];
  cell = self.countryCell;
  self.countryCell = nil;
}
</code></pre>

<p>This fixes the problem with VoiceOver but means that any time you use a custom prototype cell with storyboards you have to create a duplicate copy of the cell in a standalone XIB file and take care of loading it. This obviously somewhat reduces the benefit of using storyboards in the first place.</p>

<h3>Bug Reports</h3>

<p>Whilst this is a new problem for me it is actually a long known bug in iOS 5. I have only verified it with iOS 5.1.1 but I found Open Radar bug reports indicating it was present in iOS 5.0. The first report I found was filed back in December 2011, see <a href="http://www.openradar.me/10550644">10550644</a> and duplicated many times since then. See also <a href="http://www.openradar.me/10675427">10675427</a> and <a href="http://www.openradar.me/10763569">10763569</a> for other reports.</p>

<p>I will hold off on commenting on the state of this bug in iOS 6 until we get the final release. However even if it is fixed in iOS 6 that does not help if the bug remains for iOS 5. My guess is that most developers are only now starting to move the minimum deployment target to iOS 5 and it will be some time before iOS 6 can required. In the meantime I will add my own bug report to the list and include workaround code anytime I use storyboards.</p>

<p>I have updated the example <a href="https://github.com/kharrison/CodeExamples/tree/master/WorldFacts">WorldFacts Xcode project</a> in my <a href="https://github.com/kharrison/CodeExamples">GitHub CodeExamples repository</a> if you want to check out the changes in detail.</p>

<p><em>Updated 11 September 2012: See this <a href="http://useyourloaf.com/blog/2012/09/11/voiceover-bug-and-ios-5-tableviews-revisited.html">post</a> for an additional workaround to ensure storyboard segues work for cells created with VoiceOver active.</em></p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/09/07/prototype-table-view-cells-not-working-with-voiceover.html">Prototype Table View Cells Not Working With VoiceOver</a> was originally posted 07 Sep 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Adding A Search Bar To A Table View With Storyboards]]></title>
    
      <category term="searchdisplaycontroller"/>
    
      <category term="storyboard"/>
    
      <category term="tableviewcontroller"/>
    
    <link href="http://useyourloaf.com/blog/2012/09/06/search-bar-table-view-storyboard.html"/>
    <updated>2012-09-06T15:10:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/09/06/search-bar-table-view-storyboard</id>
    <content type="html"><![CDATA[<p><em>In this post I want to revisit the WorldFacts core data app that I previously used to illustrate creating dynamic table views with storyboards and add a search bar. The concept of a search bar is easy but in practise things can often get complicated if you are using custom cells especially if you are using a storyboard to create the table view.</em></p>

<h3>The Search Display Controller</h3>

<p>A search bar (<code>UISearchBar</code>) is a common iOS user interface element which accepts text from the user that can then be used to search or filter the data displayed to the user. It is not required but an easy way to implement and manage a search bar is to use a search display controller (<code>UISearchDisplayController</code>). The search display controller takes care of creating a table view that superimposes the search results over the original view.</p>

<p>The search display controller is initialised with a search bar and the view controller that is displaying the original content. The original view controller is typically a table view controller displaying a list of data that we want to search. Typically this original table view controller will also perform a number of delegate roles for the search bar, search display controller and search results table view.</p>

<h3>Adding A Search Bar To An Existing App.</h3>

<p>For the purposes of this post I am going to add a search bar to an existing table view based app. I created the WorldFacts app as an example on how to create dynamic <a href="http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html">prototype table view cells with storyboards</a>. It displays a list of countries with some associated data such as the country and population using a table view controller class named <code>UYLCountryTableViewController</code> implemented with a storyboard:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-06-06-001.png" alt="WorldFacts Example App" /></p>

<p>To get started I will modify the <code>UYLCountryTableViewController</code> class to declare that it conforms to the <code>UISearchDisplayDelegate</code> and <code>UISearchBarDelegate</code> protocols.</p>

<pre><code>@interface UYLCountryTableViewController () &lt;NSFetchedResultsControllerDelegate, UISearchDisplayDelegate, UISearchBarDelegate&gt;
</code></pre>

<p>I have done this in the private class extension inside the <code>UYLCountryTableViewController.m</code> file rather than in the public interface declaration since I consider it an internal implementation detail. The public interface for the class is unchanged:</p>

<pre><code>@interface UYLCountryTableViewController : UITableViewController
</code></pre>

<p>The easiest way to add the search display controller and search bar is to use Interface Builder. With the storyboard containing the table view open you need to find the combined Search Bar and Search Display Controller objects in the object library:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-05-001.png" alt="object library" /></p>

<p>Drag the objects onto the table view positioning the search bar above the prototype cells as shown below (I have highlighted the search bar in red):</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-05-002.png" alt="search bar" /></p>

<p>The outline view (see below) makes it clearer to see where the two objects end up with the search bar ending up in the table view:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-05-003.png" alt="outline" /></p>

<p>Interface builder takes care of connecting up all of the outlets from both the search bar and search display controller using the table view controller as the delegate.</p>

<h3>Configuring The Search Bar</h3>

<p>Before moving on to the implementation of the actual search code I want to look at some of the options we have to configure the search bar.</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-05-004.png" alt="search bar options" /></p>

<p>I will not go into every option as most of them are fairly obvious. I have set the Placeholder text that is displayed when the text field is empty. The more interesting option that I want to include is the use of a scope bar. This is an additional segmented control which can be used to control the scope of the search. In this case I have enabled the scope bar and entered two scopes into Interface Builder with the intention of allowing the user to search by country name or capital.</p>

<p>Note that the search bar itself does not implement any of the actual search behaviour. It is really just a set of views and controls that we can interact with using the search bar and search display controller delegates. Also note that the Placeholder text and scope titles would normally need to be localized in a real app. The final appearance of the search bar in Interface Builder is shown below with the scope bar visible below the search bar:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-05-005.png" alt="search bar appearance" /></p>

<p>With iOS 5 the search bar appearance can also be more extensively customised either individually or as a class using the appearance proxy (see this previous post on <a href="http://useyourloaf.com/blog/2012/08/24/using-appearance-proxy-to-style-apps.html">using appearance proxy to style apps</a>).</p>

<h3>Implementing The Search</h3>

<p>To implement the actual search of our country data we first need somewhere to store the search results. I have added an <code>NSArray</code> to the <code>UYLCountryTableViewController</code> for that purpose:</p>

<pre><code>@property (strong, nonatomic) NSArray *filteredList;
</code></pre>

<p>The data is stored in core data so we will need to construct a fetch request to actual perform the search. To avoid having to create the fetch request each time we will add a property to cache the object that we lazily create in the getter:</p>

<pre><code>@property (strong, nonatomic) NSFetchRequest *searchFetchRequest;
</code></pre>

<p>The getter method then either returns the existing fetch request or creates it:</p>

<pre><code>- (NSFetchRequest *)searchFetchRequest
{
  if (_searchFetchRequest != nil)
  {
    return _searchFetchRequest;
  }

  _searchFetchRequest = [[NSFetchRequest alloc] init];
  NSEntityDescription *entity = [NSEntityDescription entityForName:@"Country" inManagedObjectContext:self.managedObjectContext];
  [_searchFetchRequest setEntity:entity];

  NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
  NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
  [_searchFetchRequest setSortDescriptors:sortDescriptors];

  return _searchFetchRequest;
}
</code></pre>

<p>The fetch request is configured to fetch <code>Country</code> managed objects sorted by country name. The actual search text and scope will be handled by adding an NSPredicate to this more generic fetch request when we actually perform the search. The search method takes the search text and an integer to indicate the search scope (country or capital):</p>

<pre><code>- (void)searchForText:(NSString *)searchText scope:(UYLWorldFactsSearchScope)scopeOption
{
  if (self.managedObjectContext)
  {
    NSString *predicateFormat = @"%K BEGINSWITH[cd] %@";
    NSString *searchAttribute = @"name";

    if (scopeOption == searchScopeCapital)
    {
        searchAttribute = @"capital";
    }

    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFormat, searchAttribute, searchText];
    [self.searchFetchRequest setPredicate:predicate];

    NSError *error = nil;
    self.filteredList = [self.managedObjectContext executeFetchRequest:self.searchFetchRequest error:&amp;error];
  }
}
</code></pre>

<p>The scoreOption parameter is an enumerated type with values matching the scope bar titles defined as follows:</p>

<pre><code>typedef enum
{
  searchScopeCountry = 0,
  searchScopeCapital = 1
} UYLWorldFactsSearchScope;
</code></pre>

<p>The key to performing the search is in constructing an NSPredicate which limits the objects the fetch request will return. The predicate is constructed using the format string &#8220;%K BEGINSWITH[cd] %@&#8221;.</p>

<ul>
<li>The %K parameter allows us to specify a dynamic property name that will be substituted at runtime with the name of the core data managed object attribute we are searching. Based on the search scope we set this to either &#8220;name&#8221; or &#8220;capital&#8221;.</li>
<li>The %@ parameter specifies the value we are searching for and is substituted at runtime with the actual search text from the search bar.</li>
<li>The search comparison BEGINSWITH[cd] specifies a case and diacritic-insensitive search that begins with our search term.</li>
</ul>


<p>Finally we can release the cached fetch request in the event that we receive a memory warning:</p>

<pre><code>- (void)didReceiveMemoryWarning
{
  self.searchFetchRequest = nil;
  [super didReceiveMemoryWarning];
}
</code></pre>

<h3>Implementing The UISearchDisplayDelegate methods</h3>

<p>To actually trigger the search we need to implement two methods of the UISearchDisplayDelegate protocol to detect when both the search text and search scope has changed. The first method will deal with changes to the search text:</p>

<pre><code>- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
  UYLWorldFactsSearchScope scopeKey = controller.searchBar.selectedScopeButtonIndex;
  [self searchForText:searchString scope:scopeKey];
  return YES;
}
</code></pre>

<p>This method is called with the search string that the user has entered. We can retrieve the search bar scope from the search display controller and then call the searchForText:scope: method we saw previously. This method returns YES to indicate that the search results table view should be reloaded to show our new search results.</p>

<p>The second method we need deals with changes to the search scope:</p>

<pre><code>- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
  NSString *searchString = controller.searchBar.text;
  [self searchForText:searchString scope:searchOption];
  return YES;
}
</code></pre>

<p>This time we are passed the scope in the searchOption parameter but need to retrieve the search term from the search bar. As before we return YES to cause the results table to be reloaded.</p>

<h3>Modifying The UITableViewDataSource</h3>

<p>Now that we have some search results we need to modify our table view controller to handle the display. The key to remember is that we are now dealing with two distinct table views:</p>

<ul>
<li>The <code>UYLCountryTableViewController</code> class has a table view accessed at <code>self.tableView</code> that is used to display the original, unfiltered country data.</li>
<li>The <code>UISearchDisplayController</code> introduces a second table view accessed at <code>self.searchDisplayController.searchResultsTableView</code> that is used to show the country data search results.</li>
</ul>


<p>Each of the <code>UITableViewDataSource</code> methods that we have implemented in our table view controller needs to be modified to check which table view we are operating on when returning results. Since each of the methods has the tableView as a parameter it is trivial to compare with <code>self.tableView</code> to determine which result we need to return. The modified methods will end up with code that looks something like this:</p>

<pre><code>if (tableView == self.tableView)
{
  // Original table view
}
else
{
  // search results table view
}
</code></pre>

<p>I will avoid going into details on the code for the original table view which makes use of a fetched results controller. Instead I will focus on the modifications we make to return the search results.</p>

<h4>numberOfSectionsInTableView:</h4>

<p>The search results will be displayed in a single section so we just need to return &#8220;1&#8221; when we are not dealing with the original table view:</p>

<pre><code>- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
  if (tableView == self.tableView)
  {
    return [[self.fetchedResultsController sections] count];
  }
  else
  {
    return 1;
  }
}
</code></pre>

<h4>tableView:numberOfRowsInSection:</h4>

<p>The number of rows in the search results table view is simply the count of the number of objects we have in the filtered list:</p>

<pre><code>- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  if (tableView == self.tableView)
  {
    id &lt;NSFetchedResultsSectionInfo&gt; sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
  }
  else
  {
    return [self.filteredList count];
  }
}
</code></pre>

<h4>tableView:cellForRowAtIndexPath:</h4>

<p>The implementation of this method is interesting as it contains a small pitfall. Our original code to dequeue a reusable table view cell is as follows:</p>

<pre><code>UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:UYLCountryCellIdentifier];
</code></pre>

<p>This will either create a new cell based on the prototype we defined in the storyboard or reuse an existing cell if available. If you are not familiar with this you may want to refer back to the original post on <a href="http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html">prototype table view cells</a> where I discussed this in more detail. Unfortunately this code will break when we introduce the search results table view cell:</p>

<pre><code>*** Assertion failure in -[UISearchResultsTableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:6061
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
</code></pre>

<p>The problem is that the search results table view is created by the search display controller and does not know about the prototype table view cell we registered in the storyboard for the <code>UYLCountryTableViewController</code> class. This means that when we ask the search results table view to create a cell with identifier <code>UYLCountryCellIdentifier</code> it returns nil.</p>

<p>The Apple documentation and sample code for storyboards, table views and search bars do not provide any clear guidance on how to deal with this situation. We could go back to defining the table view cell in a separate NIB file and load it manually but that seems to defeat the point of using storyboards. The best workaround I have found so far is to always use the original table view (self.tableView) to instantiate the table view cell:</p>

<pre><code>UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:UYLCountryCellIdentifier];
</code></pre>

<p>This seems a little unusual but as far as I can tell it is perfectly safe and achieves the desired result. A bug report is on its way to Apple to see if they can clarify this situation and I will update this post if I get a response.</p>

<p>Once we have the cell we get the Country object from either the fetched results controller or the filtered list depending on which table view we are handling:</p>

<pre><code>Country *country = nil;
if (tableView == self.tableView)
{
  country = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
else
{
  country = [self.filteredList objectAtIndex:indexPath.row];
}
</code></pre>

<h4>Section Index Titles</h4>

<p>The three remaining <code>UITableViewDataSource</code> methods deal with the section index and titles. I will avoid showing each method as they are very similar and you can refer to the example code  if required. In each case we disable the section index and titles when we are dealing with the search results table:</p>

<ul>
<li>tableView:titleForHeaderInSection: returns nil for the search results.</li>
<li>sectionIndexTitlesForTableView: returns nil for the search results.</li>
<li>tableView:sectionForSectionIndexTitle:atIndex: returns 0 for the search results.</li>
</ul>


<h3>Fixing the row height</h3>

<p>There is one remaining problem with the search results table view that we need to address. The original table view defined in the storyboard for the <code>UYLCountryTableViewController</code> class uses a non-default cell row height:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-06-001.png" alt="row height" /></p>

<p>The search results table view is created by the search display controller with a default row height which needs to be changed if we want our cells to display correctly. Luckily the <code>UISearchDisplayDelegate</code> protocol gives us an easy way to override the row height when the table is first loaded:</p>

<pre><code>- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
  tableView.rowHeight = 64;
}
</code></pre>

<h3>Segue To Detailed View Controller</h3>

<p>In our original table view controller we used a storyboard defined segue to transition from the table view to the detailed country view. The <code>prepareForSegue:sender:</code> method allows us to retrieve the Country object we need to pass to the detailed view controller. Since we are using the same prototype cell we can take advantage of the same segue when the user selects a row in the search results table view. We just need to detect when the search display controller is active and retrieve the Country object from our filtered list rather than from the fetched results controller:</p>

<pre><code>- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{ 
  if ([segue.identifier isEqualToString:UYLSegueShowCountry])
  {
    Country *country = nil;
    if (self.searchDisplayController.isActive)
    {
      NSIndexPath *indexPath = [self.searchDisplayController.searchResultsTableView indexPathForCell:sender];
      country = [self.filteredList objectAtIndex:indexPath.row];
    }
    else
    {
      NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
      country = [self.fetchedResultsController objectAtIndexPath:indexPath];
    }
    UYLCountryViewController *viewController = segue.destinationViewController;
    viewController.country = country;
  }
}
</code></pre>

<h3>Adding A Search Icon To The Index</h3>

<p>At this point we have a functioning search bar for the country table view controller which allows us to search by country name or capital and transition to the detailed country view:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-06-002.png" alt="Searching" /></p>

<p>To finish up I am going to modify the section index title displayed on the right hand side to include a search icon that will scroll the table view to the top. This involves another modification to our <code>UITableViewDataSource</code> methods to adjust the section index titles. We need to insert the search icon (<code>UITableViewIndexSearch</code>) at the beginning of the array of index titles generated by the fetched results controller:</p>

<pre><code>- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
  if (tableView == self.tableView)
  {
    NSMutableArray *index = [NSMutableArray arrayWithObject:UITableViewIndexSearch];
    NSArray *initials = [self.fetchedResultsController sectionIndexTitles];
    [index addObjectsFromArray:initials];
    return index;
  }
  else
  {
    return nil;
  }
}
</code></pre>

<p>When the table view controller requests the section that corresponds to the search icon in the index we return not found and force the table view to scroll to the top. The index for the other sections is now offset by one so we need to adjust when asking the fetched results controller for the section:</p>

<pre><code>- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
  if (tableView == self.tableView)
  {
    if (index &gt; 0)
    {
      return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index-1];
    }
    else
    {
      self.tableView.contentOffset = CGPointZero;
      return NSNotFound;
    }
  }
  else
  {
    return 0;
  }
}
</code></pre>

<p>The final appearance of the index with the search icon is shown as below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-09-06-003.png" alt="search index" /></p>

<h3>Wrapping Up</h3>

<p>That was a long post for what I had originally planned as a simple topic but hopefully by building the features slowly you were able to follow along. I am not entirely happy with the way that the search display controller interacts with the results table view when using a storyboard. The workaround I presented in this post seems to do the trick but some clearer guidance from Apple would be helpful. As usual you can find the <a href="https://github.com/kharrison/CodeExamples/tree/master/WorldFacts">example WorldFacts Xcode project</a> used for this post in my <a href="https://github.com/kharrison/CodeExamples">GitHub CodeExamples repository</a> if you want to have a closer look.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/09/06/search-bar-table-view-storyboard.html">Adding A Search Bar To A Table View With Storyboards</a> was originally posted 06 Sep 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using Appearance Proxy To Style Apps]]></title>
    
      <category term="Appearance"/>
    
    <link href="http://useyourloaf.com/blog/2012/08/24/using-appearance-proxy-to-style-apps.html"/>
    <updated>2012-08-24T15:00:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/08/24/using-appearance-proxy-to-style-apps</id>
    <content type="html"><![CDATA[<p>In a <a href="http://useyourloaf.com/blog/2012/07/05/customizing-appearance-with-resizable-images.html">previous post</a> I examined how with iOS 5 it became much easier to customise the appearance of some common UIKit controls using resizable images. In this post I want to go a little further and look at how to use appearance proxies to more fully style an applications user interface.</p>

<p><em>I should mention that I am writing this post a few weeks ahead of the expected release of iOS 6. This discussion is therefore limited to only those features that are available in iOS 5.</em></p>

<h3>UIAppearance Protocol</h3>

<p>As I demonstrated in an earlier post on <a href="http://useyourloaf.com/blog/2012/07/05/customizing-appearance-with-resizable-images.html">customising appearance with resizable images</a> many UIKit controls have properties and methods allowing the tintColor, background images and other appearance aspects to be set. However in an application with a large number of controls it can quickly become unmanageable if you are have to directly customise each control.</p>

<p>Luckily Apple introduced the UIAppearance protocol with iOS 5 that has greatly reduced the work required to apply a consistent style to an application. Instead of having to customise the appearance of each UIKit control directly you can customise the appearance of a whole class of UIKit controls (e.g. all the UIButtons in an application). The UIAppearance protocol works by creating an appearance proxy for the UIKit class. Modifying the appearance of the appearance proxy modifies the appearance of all subsequent instances of that class.</p>

<p>To allow some flexibility you can also conditionally customise the appearance of a class based on the containing class. For example, a UIButton can be styled differently based on which view controller contains it. The easiest way to explain the UIAppearance protocol is by way of an example:</p>

<h3>Styling An Example App</h3>

<p>The example app that I will use for the rest of this post is not much more than a catalogue of the most common UIKit controls. Mostly the controls are not even wired-up to target:action methods so that I can skip any code not related to customising appearance. The app uses a single storyboard to define the user interface as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-23-001.png" alt="Main Storyboard" /></p>

<p>The application is navigation controller based with a <a href="http://useyourloaf.com/blog/2012/05/07/static-table-views-with-storyboards.html">static table view</a> as the root view showing each of the UIKit control types that I am going to explore in this post. Selecting a row in the table pushes a new view controller containing an example of a UIKit control onto the navigation stack. The storyboard gives you a pretty good idea of how the user interface appears using the default iOS blue colour scheme but I will try to show a before and after screenshot as we customise each view.</p>

<h3>Organising Appearance Code</h3>

<p>It is a good idea to collect as much of the appearance code as possible into a single class or method within the app. This makes life much easier when you suddenly decide that you want to completely change the appearance of an app. The approach that I am going to take with the example app is to create a custom class (<code>UYLStyleController</code>) to collect all of the appearance code. The public interface for this class is as follows:</p>

<pre><code>@interface UYLStyleController : NSObject
+ (void)applyStyle;
@end
</code></pre>

<p>The single class method +applyStyle is called from the application delegate to setup the appearance of the app before the view hierarchy is loaded. Since we are using storyboards the application delegate is pretty simple:</p>

<pre><code>- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [UYLStyleController applyStyle];
  return YES;
}
</code></pre>

<h4>UINavigationBar</h4>

<p>The first thing we do in the applyStyle class method is to customise the appearance of the navigation bar. The default navigation bar is as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-23-002.png" alt="default navigation bar" /></p>

<p>To customise the navigation bar we will apply a custom background image and modify the text attributes of the title. We also need to modify the appearance of the back button when we push a view controller onto the navigation stack as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-23-003.png" alt="default back button" /></p>

<p>To get started we first need to create some resizable images to use for the navigation bar. I covered this approach in detail in the previous post on <a href="http://useyourloaf.com/blog/2012/07/05/customizing-appearance-with-resizable-images.html">customising appearance with resizable images</a> so I will briefly recap here. Since the navigation bar on the iPhone has different heights when in portrait and landscape orientations we need to create four different images as follows:</p>

<ul>
<li>navbar.png - 44 pixels high for portrait mode (normal resolution)</li>
<li>navbar@2x.png - 88 pixels high for portrait mode (retina resolution)</li>
<li>navbar-landscape.png - 32 pixels high for landscape (normal resolution)</li>
<li>navbar-landscape@2x.png - 64 pixels high for landscape (retina resolution)</li>
</ul>


<p>The standard resolution navigation image has two end caps each of which is 20 pixels wide separated by a 1 pixel wide strip as follows:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-23-004.png" alt="nav bar cap insets" /></p>

<p>The landscape image is similar except that the height is only 32 pixels and of course the corresponding @2x image files have all dimensions doubled. The portrait and landscape resizable images are created using the resizableImageWithCapInsets method to specify the 20 pixel insets.</p>

<pre><code>+ (void)applyStyle
{
  UIImage *navBarImage = [UIImage imageNamed:@"navbar"];
  navBarImage = [navBarImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20.0, 0, 20.0)];

  UIImage *navBarLandscapeImage = [UIImage imageNamed:@"navbar-landscape"];
  navBarLandscapeImage = [navBarLandscapeImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20.0, 0, 20.0)];
</code></pre>

<p>We then need to get the appearance proxy object for the UINavigationBar class and use it to set the background image for both portrait and landscape dimensions:</p>

<pre><code>UINavigationBar *navigationBarAppearance = [UINavigationBar appearance];
[navigationBarAppearance setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];
[navigationBarAppearance setBackgroundImage:navBarLandscapeImage forBarMetrics:UIBarMetricsLandscapePhone];
</code></pre>

<p>The next thing we will do is to customise the text attributes of the title. The font, text colour and shadow can all be customised by supplying a dictionary of text attributes. In this case we will just set the text colour using the UITextAttributeTextColor key:</p>

<pre><code>NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor grayColor], UITextAttributeTextColor, nil];
[navigationBarAppearance setTitleTextAttributes:textAttributes];
</code></pre>

<p>The navigation bar now looks as shown below with our custom background image and text settings:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-23-005.png" alt="custom navigation bar" /></p>

<p>To complete the navigation bar customisation we need to also change the style of the back button to replace the default blue style:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-23-006.png" alt="default back button" /></p>

<p>Since the back button height varies with the height of the navigation bar when in landscape orientation we will need two resizable images (plus the retina @2x versions) for the back button. The images are created with a 25 pixel inset on the left and a 6 pixel inset on the right as follows:</p>

<pre><code>UIImage *backButtonImage = [UIImage imageNamed:@"back-button"];
backButtonImage = [backButtonImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 25.0, 0, 6.0)];

UIImage *backButtonLandscapeImage = [UIImage imageNamed:@"back-button-landscape"];
backButtonLandscapeImage = [backButtonLandscapeImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 25.0, 0, 6.0)];
</code></pre>

<p>The UIBarButtonItem appearance proxy can then be used to set the background image of the back button for both portrait and landscape orientations:</p>

<pre><code>UIBarButtonItem *barButtonItemAppearance = [UIBarButtonItem appearance];
[barButtonItemAppearance setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[barButtonItemAppearance setBackButtonBackgroundImage:backButtonLandscapeImage forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
</code></pre>

<p>The final effect is as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-23-007.png" alt="custom back button" /></p>

<h4>View Controller Background</h4>

<p>Before getting into the various UIKit controls I should probably mention one small detail about the view controller class that is used for each of the detailed views. Since the application is not doing anything useful other than illustrating how to modify appearance it uses the same view controller class (<code>UYLRotatingViewController</code>) for each of the views. As the name of the controller suggests the main purpose of this class is to enable interface rotation. However since it is common to each of the views we can also implement the viewDidLoad method to set the view background colour for all of the views in one place. The full implementation of the class is shown below:</p>

<pre><code>@implementation UYLRotatingViewController
- (void) viewDidLoad
{
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor lightGrayColor];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
  return YES;
}
@end
</code></pre>

<h4>UIButton</h4>

<p>To explore how to customise the appearance of the UIButton I will use a view containing a set of buttons arranged as a numeric keypad as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-001.png" alt="default button" /></p>

<p>The effect that I want to implement is to add a background image to each button using an approach similar to the way we customised the navigation bar. However in this case I want to use a different background image for some of the buttons. The objective is to make the buttons numbered 1-9 grey, the OK button green, the zero button orange and the reset button red. In all cases I will use resizable background images to create a gradient effect with cap insets to provide the rounded corners.</p>

<p>For the basic button appearance I have created a button image (<code>steel-button.png</code>) that is 41 pixels wide and 44 pixels high. I will not mention it again but all of these images also have @2x versions with double the dimensions. The cap inset for the rounded corners is 20 pixels on each side.</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-002.png" alt="steel button" /></p>

<p>We have seen how to create a resizable image with cap insets a number of times so I will just show the code without further comment:</p>

<pre><code>UIImage *defaultButtonImage = [UIImage imageNamed:@"steel-button"];
defaultButtonImage = [defaultButtonImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20.0, 0, 20.0)];
</code></pre>

<p>Now I could just get the appearance proxy object for the UIButton class and use it to set the background image. However in this case I am going to be a little more restrictive and only customise UIButton objects that are contained by the <code>UYLRotatingViewController</code> view controller. This is generally a good approach when customising UIButton as it turns up in lots of different places in a user interface. For example, if I use the UIButton appearance proxy directly I would also end up modifying the disclosure indicators shown in the root table view.</p>

<p>To specify that you only want to customise the appearance of an object when it is contained by another class (or classes) you use the appearanceWhenContainedIn method and provide a nil terminated list of appearance container classes. In this case we have just a single container class:</p>

<pre><code>[[UIButton appearanceWhenContainedIn:[UYLRotatingViewController class], nil] setBackgroundImage:defaultButtonImage forState:UIControlStateNormal];
</code></pre>

<p>That takes care of the default case for the numbers 1-9 but the other buttons are a little more tricky. To customise the zero, OK and Reset buttons we make use of the fact that the appearance protocol will also work with our own custom subclasses of the standard UIKit controls. So we can subclass UIButton for each of our custom buttons and apply the appearance changes to those subclasses.</p>

<p>A similar approach will work for all three buttons so I will only discuss the OK button. The first thing we will do is create a custom subclass of UIButton named UYLOkButton. This subclass is trivial as it has no additional implementation code:</p>

<pre><code>@interface UYLOkButton : UIButton
@end

@implementation UYLOkButton
@end
</code></pre>

<p>Once we have this class defined we can customise the button in the storyboard to specify the UYLOkButton class.</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-003.png" alt="ok button" /></p>

<p>The code to set the background image of the UYLOkButton class is similar to before except that we use our custom class in place of the generic UIButton class:</p>

<pre><code>UIImage *okButtonImage = [UIImage imageNamed:@"green-button"];
okButtonImage = [okButtonImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20.0, 0, 20.0)];
[[UYLOkButton appearanceWhenContainedIn:[UYLRotatingViewController class], nil] setBackgroundImage:okButtonImage forState:UIControlStateNormal];
</code></pre>

<p>The zero and reset buttons use a similar technique so I will not show the code. The only addition is that I change the text color for the reset button to white to make it show up more clearly:</p>

<pre><code>[[UYLResetButton appearanceWhenContainedIn:[UYLRotatingViewController class], nil] setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
</code></pre>

<p>The final effect is shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-004.png" alt="keypad" /></p>

<h4>UIActivityIndicator, UIProgressView and UILabel</h4>

<p>The next set of controls I am going to look at are much more straightforward. The activity view contains some UILabel items, a large white UIActivityIndicator and a UIProgressView. The default appearance is shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-005.png" alt="default activity" /></p>

<p>I am going to use a mix of mostly dark and light grey colours for the various elements so I will start by defining those colours:</p>

<pre><code>UIColor *mainColor = [UIColor darkGrayColor];
UIColor *altColor = [UIColor lightGrayColor];
</code></pre>

<p>Now I will set the text color for all UILabel objects that appear in my container view controller:</p>

<pre><code>UILabel *labelAppearance = [UILabel appearanceWhenContainedIn:[UYLRotatingViewController class], nil];
[labelAppearance setTextColor:mainColor];
</code></pre>

<p>The UIActivityIndicator does not provide much in the way of customisation options but one thing we can do is change the colour. In this we will change it to red:</p>

<pre><code>[[UIActivityIndicatorView appearance] setColor:[UIColor redColor]];
</code></pre>

<p>Finally we will adjust the progress view to use our own colour scheme for the various parts of the track:</p>

<pre><code>[[UIProgressView appearance] setProgressTintColor:mainColor];
[[UIProgressView appearance] setTrackTintColor:altColor];
</code></pre>

<p>The end result of these customisations is shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-006.png" alt="custom activity" /></p>

<h4>UISwitch</h4>

<p>The default UISwitch appearance is shown in the screenshot below. Note that the UILabel elements in this view are already using the custom appearance we created previously:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-007.png" alt="default switch" /></p>

<p>With iOS 5 we can customise the tint color for the ON portion of the switch:</p>

<pre><code>[[UISwitch appearance] setOnTintColor:altColor];
</code></pre>

<p>This gives the switches the following appearance:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-008.png" alt="custom switch" /></p>

<h4>UISlider</h4>

<p>The default UISlider appearance is similar to the UIProgressView with the addition of the progress indicator &#8220;thumb&#8221;:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-009.png" alt="default slider" /></p>

<p>We can set the both the minimum (left of thumb) and maximum (right of thumb) track tint and also the tint color of the thumb appearance as follows:</p>

<pre><code>[[UISlider appearance] setMinimumTrackTintColor:mainColor];
[[UISlider appearance] setMaximumTrackTintColor:altColor];
[[UISlider appearance] setThumbTintColor:[UIColor redColor]];
</code></pre>

<p>The result is shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-010.png" alt="custom slider" /></p>

<h4>UISegmentedControl</h4>

<p>The last UIKit control that I am going to look at is the UISegmentedControl which with two segments has the following default appearance when the first segment is selected:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-011.png" alt="default segment" /></p>

<p>To customise the UISegmentedControl we will use our previously created orange and steel button resizable images to set the background for both the normal and selected states of a segment:</p>

<pre><code>[[UISegmentedControl appearance] setBackgroundImage:defaultButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:zeroButtonImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
</code></pre>

<p>There is one small complication with the UISegmentedControl in that it also has an image for the divider between the segments. At present if we do nothing else our segmented control is left with an ugly default blue divider:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-012.png" alt="segment divider" /></p>

<p>To fix the divider we need to create an image 1 pixel wide and 44 pixels hide to act as the divider. We can then set the divider as follows:</p>

<pre><code>UIImage *dividerImage = [UIImage imageNamed:@"divider"];
[[UISegmentedControl appearance] setDividerImage:dividerImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
</code></pre>

<p>The documentation for UISlider suggests that you should set divider images for the various combinations of selected and normal segments. In this case I found it sufficient to just cover the default case of both segments in the normal state. The resulting appearance is shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-24-013.png" alt="custom segment" /></p>

<h3>Wrapping Up</h3>

<p>I hope that gives you an idea on how to make use of appearance proxies when customising the appearance of an iOS app. I have not covered every option for every control as once you get the idea the technique is pretty much always the same. The example <a href="https://github.com/kharrison/CodeExamples/tree/master/Styles">Styles</a> Xcode project that accompanies this post can be found in my <a href="https://github.com/kharrison/CodeExamples">GitHub Code Examples</a> repository should you want to take a closer look.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/08/24/using-appearance-proxy-to-style-apps.html">Using Appearance Proxy To Style Apps</a> was originally posted 24 Aug 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Stop Xcode Automatic Termination]]></title>
    
      <category term="Xcode"/>
    
      <category term="osx"/>
    
    <link href="http://useyourloaf.com/blog/2012/08/13/xcode-automatic-termination.html"/>
    <updated>2012-08-13T21:35:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/08/13/xcode-automatic-termination</id>
    <content type="html"><![CDATA[<p>Lion and now also Mountain Lion have an annoying tendency to <em>helpfully</em> terminate applications for you. I spotted a tip by Matt Neuburg over on the <a href="http://tidbits.com/article/13174">TidBITS blog</a> this week which offers a solution that I think is worth filing for future reference. First though let me describe the problem as it most often impacts me with Xcode. I should say this problem and the solution are not specific to Xcode I just happen to notice it most with Xcode.</p>

<h3>The Problem</h3>

<p>My ageing Mac can take a little while to start Xcode which means that I often find myself switching to another application whilst I am waiting. Inevitably I get distracted and it can be a minute or two before I attempt to switch back to Xcode to open a project and do some work. Alternatively I may be using Xcode, close a project so it no longer has any active windows and switch to another application. In both situations if I am away from Xcode for more than a minute or two there is a good chance that Xcode will no longer be visible in the dock or in the application switcher with Command-Tab.</p>

<h3>Automatic Termination</h3>

<p>At first this behaviour is a little confusing and you may even be tempted to assume Xcode has crashed. Actually it is not a bug but a feature known as <em>automatic termination</em> introduced with Lion and still present in Mountain Lion. It allows OS X to terminate applications that it decides are no longer in use to reclaim resources. In theory this is optional for an application but unfortunately it seems that Xcode has decided to opt-in.</p>

<p>This is a familiar situation for an iOS application. Apple has always made it clear that inactive iOS applications can expect to be terminated and should be designed with that in mind. The iOS task switcher also does a good job of hiding which applications are actually running so in theory a user may never know when switching between applications. In practise it is not always totally invisible to the user but it seems to be a reasonable compromise on an iOS device.</p>

<p>Automatic termination of applications on a desktop class machine seems to be a much less reasonable compromise. OS X has access to much greater resources and it seems unnecessary to start terminating applications without user intervention. Even worse is the fact that the application disappears from both the dock (unless you opted to keep it there permanently) and from the application switcher forcing you to relaunch it.</p>

<p>To add further insult to injury the application is not even really terminated. In my case whenever I spot that Xcode has disappeared a quick <code>ps</code> from the command-line or checking activity monitor will reveal that the process is actually still running. This is a further &#8220;feature&#8221; where OS X may decide to keep the process memory resident in case you decide to relaunch it. In fact since on my Mac the initial Xcode load takes several seconds this difference in launch time is very noticeable. After OS X has helpfully &#8220;terminated&#8221; Xcode for me it reappears almost instantly when I relaunch it. Of course if OS X had not &#8220;terminated&#8221; it for me in the first place I would not need to relaunch it so the benefit is dubious&#8230;</p>

<h3>The Solution</h3>

<p>I recognise that opinion is still divided on many of the iOS style features that Apple has brought to Lion and Mountain Lion. If you are not convinced by the benefits of OS X automatically terminating applications here is the command to disable the feature:</p>

<pre><code>defaults write -g NSDisableAutomaticTermination -bool yes
</code></pre>

<p>I found I had to reboot for the change to take effect but that was most likely because Xcode was still running as I previously explained. A logout or manually killing the Xcode process hiding in the background would probably have worked as well.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/08/13/xcode-automatic-termination.html">Stop Xcode Automatic Termination</a> was originally posted 13 Aug 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Keeping Mountain Lion Awake]]></title>
    
      <category term="osx"/>
    
    <link href="http://useyourloaf.com/blog/2012/08/09/keeping-mountain-lion-awake.html"/>
    <updated>2012-08-09T16:50:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/08/09/keeping-mountain-lion-awake</id>
    <content type="html"><![CDATA[<p>After upgrading to Mountain Lion I have been hitting some problems with my Mac sleeping when I was expecting it be doing some work. Typically this happens when I leave it running a script that I expect to take several hours. On my return I find the network connection has dropped and the machine has gone to sleep leaving the job unfinished. The explanation and solution lies in the changes to power management that Mountain Lion introduced.</p>

<p>You can read more about the power management changes in <a href="http://arstechnica.com/apple/2012/07/os-x-10-8/18/#power-management">John Siracusa&#8217;s epic Mountain Lion review</a> and also in WWDC 2012 session 711. In short, Mountain Lion is noticeably more aggressive when deciding to sleep compared to previous releases. In particular my problem is caused because disk activity is no longer sufficient to prevent the computer sleeping. One way to prevent the problem is by setting the computer sleep time to &#8220;Never&#8221; in the Energy Saver system preferences pane:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-08-03-001.png" alt="Energy Saver Preference Pane" /></p>

<p>That however means that the system will never sleep which is certainly not what I want. When the system is truly idle I want it to save power by shutting down. A better approach is to use <em>Power Assertions</em> to tell the system when I have some work and I that I would prefer it not to sleep.</p>

<h3>Power Assertions</h3>

<p>A power assertion is way to provide a hint to OS X that you are busy doing something. If possible it should not allow the computer to sleep when the user is idle. Apple provides SDK calls to allow an application to create and release power assertions but in my case there are two command-line utilities that will do the job.</p>

<h4>pmset</h4>

<p>The pmset command (<code>/usr/bin/pmset</code>) provides command-line access to many of the power management settings that are visible in the Energy Saver preferences pane. In addition it provides a way to view and manage power assertions. For example if I use iTunes to play some music it allows the display to sleep but a power assertion prevents the system from entering the idle sleep mode. You can see this using the pmset command as follows:</p>

<pre><code>$ pmset -g assertions
08/08/2012 23:41:20 BST  
Assertion status system-wide:
   PreventUserIdleDisplaySleep    0
   PreventSystemSleep             0
   PreventUserIdleSystemSleep     1
   ExternalMedia                  1
   DisableLowPowerBatteryWarnings 0
   UserIsActive                   0
   ApplePushServiceTask           0
   BackgroundTask                 0

Listed by owning process:
  pid 5871(iTunes): [0x000000010000093e] 00:00:08 PreventUserIdleSystemSleep named: "Nameless (via IOPMAssertionCreate)" 
  pid 29(powerd): [0x000000090000012c] 61:28:54 ExternalMedia named: "com.apple.powermanagement.externalmediamounted" 
</code></pre>

<p>Note that the 0 and 1 indicate the state of the assertion not the total count of assertions. A list of processes owning the assertions is also displayed so you can check who created each assertion. In this case there is also an assertion created by the powerd process for an external drive that is attached. Note that this ExternalMedia assertion will not prevent the system from sleeping.</p>

<p>You can also view the power management log to see the create and release power assertion events:</p>

<pre><code>$ pmset -g log
08/08/2012 23:41:17 BST  Assertions             PID 5871(iTunes) Created PreventUserIdleSystemSleep "Nameless (via IOPMAssertionCreate)" 00:00:08  id:0x100000984 Aggregate:0x100242    
08/08/2012 23:41:35 BST  Assertions             PID 5871(iTunes) Released PreventUserIdleSystemSleep "Nameless (via IOPMAssertionCreate)" 00:00:26  id:0x100000984 Aggregate:0x100242
</code></pre>

<p>If you want to create a power management assertion to prevent the computer entering the idle sleep mode you can use the following command in a terminal session:</p>

<pre><code>$ pmset noidle
Preventing idle sleep (^C to exit)...
</code></pre>

<p>As we have already seen you can check that the power assertion has been created using the pmset command from a second terminal window:</p>

<pre><code>$ pmset -g assertions
   ...
   PreventUserIdleSystemSleep     1
   ...
Listed by owning process:
  pid 25194(pmset): [0x00000001000014ff] 00:00:51 NoIdleSleepAssertion named: "pmset prevent sleep" 
</code></pre>

<p>When you are done you can hit control-C to exit and release the power assertion. The pmset command is fine but not the most convenient solution when you want a power assertion that lasts for the duration of a script execution.</p>

<h4>caffeinate</h4>

<p>If you want to prevent the system from sleeping whilst you run a script or utility there is a better option with Mountain Lion. The caffeinate (<code>/usr/bin/caffeinate</code>) command allows you create an assertion like pmset. Where caffeinate gets more useful is that it takes an optional argument specifying a script or utility it should execute. The power assertion is then maintained until the script completes. For example, to create a power assertion that prevents idle sleep whilst the script longtask.sh executes:</p>

<pre><code>$ caffeinate ./longtask.sh
</code></pre>

<p>As before you can use pmset to see this assertion:</p>

<pre><code>$ pmset -g assertions
   ...
   PreventUserIdleSystemSleep     1
   ...
Listed by owning process:
  pid 26187(caffeinate): [0x00000001000015cd] 00:00:11 PreventUserIdleSystemSleep named: "caffeinate command-line tool" 
    Details: caffeinate asserting on behalf of ./longtask.sh
    Localized=THE CAFFEINATE TOOL IS PREVENTING SLEEP.
</code></pre>

<p>The caffeinate command has a number of other useful options to prevent the display from sleeping and to create timed power assertions (use <code>man caffeinate</code> for further details). If you are interested Apple has also open sourced the code, you can find it on the <a href="http://opensource.apple.com/source/PowerManagement/PowerManagement-321.2.9/caffeinate/caffeinate.c">Apple Source Code Site</a>.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/08/09/keeping-mountain-lion-awake.html">Keeping Mountain Lion Awake</a> was originally posted 09 Aug 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Automatic Property Synthesis with Xcode 4.4]]></title>
    
      <category term="Xcode"/>
    
      <category term="objective-c"/>
    
    <link href="http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4.html"/>
    <updated>2012-08-01T20:10:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4</id>
    <content type="html"><![CDATA[<p>The release of OS X 10.8 Mountain Lion this week also brought us an Xcode release with some long awaited Objective-C improvements. If you upgraded your development machine to Mountain Lion you should check the Mac App Store for the Xcode 4.4 update. If you are more cautious and are staying with OS X 10.7 Lion you can still upgrade to Xcode 4.4 (according to the release notes you will need to be on at least 10.7.4).</p>

<p>One of the reasons that you may want to upgrade to Xcode 4.4 is that it includes Apple LLVM compiler 4.0 that adds a number of new Objective-C Language features. Even better most of the new features are backwardly compatibile with older versions of iOS. To make is easier to understand which features are available for which tool and OS releases Apple has published a useful <a href="https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/ObjCAvailabilityIndex/_index.html#//apple_ref/doc/uid/TP40012243">Objective-C Feature Availability Index</a>.</p>

<h3>Default Synthesis Of Properties</h3>

<p>The new Objective-C feature that I want to examine in this post is the default synthesis of properties. Here is the description from the <a href="http://clang.llvm.org/docs/LanguageExtensions.html">Clang Language Extensions</a> web page:</p>

<blockquote><p>Clang provides support for autosynthesis of declared properties.
Using this feature, clang provides default synthesis of those
properties not declared @dynamic and not having user provided
backing getter and setter methods.</p></blockquote>

<p>To understand what this means consider a typical class interface implemented with LLVM Compiler 3.x that I used in a recent code example:</p>

<pre><code>@interface UYLCountryViewController : UIViewController
@property (nonatomic, strong) Country *country;
@end
</code></pre>

<p>This class has a public property named <code>country</code> defined in the class interface backed by an instance variable that is synthesized in the class implementation:</p>

<pre><code>@implementation UYLCountryViewController
@synthesize country=_country;
</code></pre>

<p>The @synthesize directive tells the compiler to generate the getter and setter accessor methods for us saving a lot of error prone typing. In this case I also chose to name the instance variable using the common naming convention of prefixing the property with an underscore. As we will see shortly that turns out to be a fortunate choice. Of course, even though we asked the compiler to generate the accessor methods we can still choose to provide our own implementation if we want to. This gives us the flexibility to specify a custom getter, for example, and still have the compiler generate the setter or vice versa.</p>

<h3>Eliminate Code With Autosynthesis</h3>

<p>With Xcode 4.4 and LLVM Compiler 4.0 the @synthesize directive is no longer required as it will be provided by default. That means in most cases you now only need the @property and the compiler takes care of everything else for you. As before you can place the @property directive in the class interface if you want it to be public or in a private class extension in the class implementation file. Either way if you do nothing else the compiler will add an instance variable and implementations for the required accessor methods for you. By default the instance variable is named by prefixing the property name with an underscore.</p>

<p>To give another example, if you have a property named <code>person</code> the compiler will produce code as if you had written the following:</p>

<pre><code>@synthesize person=_person;
</code></pre>

<p>The accessor methods that are created by the compiler will as always implement the accessor semantics specified in the @property statement. So if you specify a <code>readonly</code> property the compiler will not for example generate a setter method. This really helps remove all of the boilerplate code previously required by Objective-C when defining instance variables.</p>

<h3>Naming Conventions For Instance Variables</h3>

<p>There are some subtle implementation issues you need to be aware of before you delete all of the @synthesize statements from your existing code. Most importantly a lot will depend on how you have been naming your instance variables. Now I should say that even for the relatively short period of time that I have been using Objective-C I have seen a lot of conflicting advice over how you should name instance variables.</p>

<p>One piece of &#8220;advice&#8221; that often gets mentioned is that you should not use a leading underscore for your instance variables as it is reserved by Apple. However since a lot of Apple sample code and Xcode templates use a leading underscore and I have never found an Apple statement to that effect I long ago adopted that convention. (Also see WWDC 2012 session 405 where an Apple engineer confirms that the leading underscore is not reserved by Apple for instance variable names.) Hence all of my @synthesize statements tend to look like this:</p>

<pre><code>@synthesize myIvar=_myIvar;
</code></pre>

<p>This now turns out to have been a good choice since this is exactly what the autosynthesis of properties assumes. This means in <em>most</em> simple cases you can simply remove the @synthesize statement.</p>

<h3>When To Supply The Instance Variable</h3>

<p>Most of the time the compiler will add the ivar for you when it adds the required accessor methods. However there are certain situations where you will still need to add the instance variable for yourself. In general the compiler will generate the instance variable automatically any time it generates at least one of the accessor methods. Some examples should make this clearer:</p>

<h4>Readonly Property With Non-Default Getter</h4>

<p>This first example is the case where you have a readonly property such as the following example:</p>

<pre><code>@property (readonly) NSArray *myArray;
</code></pre>

<p>If you supply your own implementation of the getter accessor method you might write something like this:</p>

<pre><code>- (NSArray *)myArray
{
  return _myArray;
}
</code></pre>

<p>This however generates a compiler error complaining that &#8216;_myArray&#8217; is an undeclared identifier. In the case of a readonly property there is only one accessor method, the getter. If we supply our own implementation the compiler makes the assumption that we are taking complete control of the implementation details and does not supply the instance variable. This flexibility also allows for those situations where you declare a property which is not backed by an instance variable.</p>

<p>To remove the compiler error you can just declare the instance variable yourself or request the compiler to do it for you with the @synthesize statement:</p>

<pre><code>@synthesize myArray=_myArray;
</code></pre>

<p>Note that if you add the @synthesize statement you need to make sure that the name of the instance variable is consistent with the name used in the accessor method. In the getter method we reference _myArray so we need to specify that name in the @synthesize statement. By default if you do not specify a name for the instance variable the @synthesize statement will use the property name (without the leading underscore).</p>

<p>So the following would still generate a compiler error as it would create an instance variable named myArray and not the _myArray that we are using in the getter:</p>

<pre><code>@synthesize myArray;  // equivalent to @synthesize myArray=myArray;
</code></pre>

<h4>Readwrite Property With Non-Default Getter and Setter</h4>

<p>This situation is similar to the readonly property with our own getter method. If we have a readwrite property the compiler will not create the instance variable if we implement <em>both</em> the getter and setter methods. So if we declare the following property (readwrite is the default if not specified):</p>

<pre><code>@property (strong, nonatomic) NSNumberFormatter *decimalFormatter;
</code></pre>

<p>We can declare our own getter method to lazily instantiate the number formatter as shown below and the compiler will supply both the setter and the instance variable (named _decimalFormatter) for us automatically.</p>

<pre><code>- (NSNumberFormatter *)decimalFormatter
{
  if (!_decimalFormatter)
  {
    _decimalFormatter = [[NSNumberFormatter alloc] init];
    [_decimalFormatter setNumberStyle:NSNumberFormatterDecimalStyle];        
  }
  return _decimalFormatter;
}
</code></pre>

<p>However if we also supply an implementation for the setter, -(void)setDecimalFormatter we will get a compiler error telling us that the _decimalFormatter is undeclared. In that situation we again need to go back to telling the compiler to synthesize the variable for us paying attention to the name:</p>

<pre><code>@synthesize decimalFormatter=_decimalFormatter;
</code></pre>

<h4>Protocols</h4>

<p>I had not originally considered how properties declared as part of a protocol are impacted by this new behaviour. Luckily I saw this <a href="https://twitter.com/secboffin/status/230320103479201792">tweet</a> from Graham Lee (@secboffin) yesterday which provides the answer:</p>

<blockquote><p>&#8220;Warning: auto property synthesis will not synthesize a property
declared in a protocol.&#8221; Nice to know.</p></blockquote>

<p>What this means if that if we have a protocol that includes a property such as the following:</p>

<pre><code>@protocol someProtocol &lt;NSObject&gt;
@property (nonatomic, strong) NSString *name;
@end
</code></pre>

<p>Any class that adopts this protocol will need to explicitly declare or synthesize the accessors and instance variable for the name property. The compiler generates a warning on the class implementation as a reminder in case you forget.</p>

<h3>Atomic Properties</h3>

<p>This is nothing new and does not change the rules about instance variable synthesis but I think it is worth recalling what happens with atomic properties. The getter and setter methods for an atomic property need to ensure that they do not interfere with each other when called from different threads. For example, the getter method should not be able to retrieve a value whilst the setter is in the process of setting it. This synchronisation means that you cannot implement one of the accessors and have the compiler supply the other.</p>

<p>I mention it here in passing as the issue can catch you out since properties are atomic by default. So for example if we declare the following property:</p>

<pre><code>@property (strong) NSString *name:
</code></pre>

<p>This is actually an atomic property so if we add our own implementation of the getter method but do not also supply the setter we will get a compiler warning:</p>

<pre><code>Writable atomic property 'name' cannot pair a synthesized setter with a user defined getter
</code></pre>

<p>The solution is to either implement the setter or change the property to nonatomic (assuming you do not need the accessors to be thread-safe).</p>

<pre><code>@property (nonatomic, strong) NSString *name:
</code></pre>

<h3>Converting Existing Code</h3>

<p>There is no reason why you have to go back and start deleting @synthesize statements from existing code since the default action maintains backwards compatibility. Of course if you enjoy deleting code or you are modifying a class it might be an idea to clean things up when possible.</p>

<p>I came across a good example of the issues you can get with existing code whilst playing around with the WorldFacts project I created recently to experiment with storyboards. This project was created using an Xcode template and includes core data. You can refer to the project in my <a href="https://github.com/kharrison/CodeExamples">CodeExamples repository</a> for the final result but below are my notes on attempting to remove all of the @synthesize statements from this project:</p>

<h4>UYLAppDelegate</h4>

<p>The application delegate defines properties for the core data stack and also the UIWindow:</p>

<pre><code>@property (strong, nonatomic) UIWindow *window;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
</code></pre>

<p>The class implementation includes @synthesize statements for each property but whoever created the template decided to use a double underscore to prefix the core data instance variable names (but not the window):</p>

<pre><code>@synthesize window = _window;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
</code></pre>

<p>The _window instance variable is never directly accessed so we can safely delete the first @synthesize statement and let the compiler handle the details.</p>

<p>The Xcode template follows the common pattern of lazily instantiating the core data stack in the getter method for each of the core data properties. I will not show the code here but they obviously refer to an instance variable with a double underscore (e.g. __managedObjectContext). This could cause an issue if we were relying on the compiler to synthesize the instance variable. However in this case we are dealing with a readonly property where we implement the getter so the compiler will leave us alone. This means we have to leave the @synthesize statement to explicitly request the compiler generate the instance variable. You could also rename the variables to use a single underscore but in this case I saw little point in making the change.</p>

<p>So in this case I only managed to remove one of the @synthesize statements.</p>

<h4>UYLCountryTableViewController</h4>

<p>The table view controller (UYLCountryTableViewController) has three instances of the @synthesize statement:</p>

<pre><code>@synthesize managedObjectContext=__managedObjectContext;
@synthesize fetchedResultsController=__fetchedResultsController;
@synthesize decimalFormatter=_decimalFormatter;
</code></pre>

<p>Here both the managedObjectContext and fetchedResultsController properties use a double underscore for the ivar name. In addition we implement getter methods for both the fetchedResultsController and decimalFormatter properties.</p>

<p>The managedObjectContext ivar is never directly accessed in the controller so we can delete the @synthesize statement without impact. Note that this does actually change the name of the ivar but since we are using compiler generated accessors it does not cause us a problem.</p>

<p>If we delete the @synthesize statement for the fetchedResultsController property we will get a compiler error in our getter implementation as the <code>__fetchedResultsController</code> ivar will then be undefined. In this case I think it makes sense to rename the ivar in the getter to <code>_fetchedResultsController</code> and delete the @synthesize.</p>

<p>Finally we can delete the @synthesize statement for the decimalFormatter since we are already using the default ivar name in our getter implementation.</p>

<h4>UYLCountryViewController</h4>

<p>The remaining view controller in the project (UYLCountryViewController) is much simpler. It has one public property and a number of private properties all with compiler synthesized accessors. There are no accessor methods or direct accesses to any of the instance variables in our code. In this case we can simply delete all of the following @synthesize statements:</p>

<pre><code>@synthesize country=_country;
@synthesize area=_area;
@synthesize capital=_capital;
@synthesize continent=_continent;
@synthesize currency=_currency;
@synthesize phone=_phone;
@synthesize population=_population;
@synthesize tld=_tld;
</code></pre>

<h3>Wrapping Up</h3>

<p>I like any improvements to the compiler that result in us having to write less code. Compared to a couple of years ago a lot of the boilerplate code from class interfaces is now no longer required. We are now at the point where apart from some special cases the only code required to add instance variables to a class is the @property statement.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4.html">Automatic Property Synthesis with Xcode 4.4</a> was originally posted 01 Aug 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Formatters and Locale Changes]]></title>
    
      <category term="cocoa"/>
    
      <category term="localization"/>
    
    <link href="http://useyourloaf.com/blog/2012/07/09/formatters-and-locale-changes.html"/>
    <updated>2012-07-09T20:37:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/07/09/formatters-and-locale-changes</id>
    <content type="html"><![CDATA[<p>I recently posted about some of the common ways of using <a href="http://useyourloaf.com/blog/2012/06/14/using-number-formatters.html">number formatters</a>. In doing so I omitted to mention that is common to cache both number and date formatters in iOS applications and a small issue this can cause if a user changes the device locale for a running app.</p>

<h3>Caching Formatters</h3>

<p>When you need a date or number formatter in a view controller it is often a good idea to cache the resulting object once you have created it. Consider for example a table view cell that uses both a number and date formatter:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-09-001.png" alt="cell format uk" /></p>

<p>It would be wasteful to create new formatters each time we need to layout a cell. A more efficient approach is to create them once in the view controller and cache the formatter objects in instance variables. You could do this in a method such as viewDidLoad but for reasons that I will explain shortly it can be more convenient to use a getter method to lazily instantiate each formatter.</p>

<p><em>I should note at this point that all of the following code snippets assume iOS 5 with ARC enabled. If you are targeting iOS 4 or earlier you will need to take care of memory management</em></p>

<p>Assuming that my table view controller class is named UYLMasterViewController I could add properties for the two formatters to a private class extension as follows (in UYLMasterViewController.m):</p>

<pre><code>@interface UYLMasterViewController ()
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSNumberFormatter *numberFormatter;
@end
</code></pre>

<p>I like to place properties like this in the private class extension rather than in the public class interface as they represent internal implementation details which should remain private. It also has the benefit of keeping the interface (.h) file clear of clutter. The corresponding instance variables are synthesized in the class implementation:</p>

<pre><code>@implementation UYLMasterViewController

@synthesize dateFormatter=_dateFormatter;
@synthesize numberFormatter=_numberFormatter;
</code></pre>

<p>This creates a default getter and setter for each ivar but we will create our own getter methods to allow the formatters to be configured the way we want them. The getter method for the date formatter which will show just the month and year could be written as follows:</p>

<pre><code>- (NSDateFormatter *)dateFormatter
{
  if (_dateFormatter == nil)
  {
    _dateFormatter = [[NSDateFormatter alloc] init];
    [_dateFormatter setDateFormat:@"MMMM yyyy"];
  }
  return _dateFormatter;
}
</code></pre>

<p>If the formatter does not already exist it will be created and stored in the ivar otherwise the existing object is returned. Likewise to format the number with locale specific grouping and decimal separators we could write the getter for the number formatter as follows:</p>

<pre><code>- (NSNumberFormatter *)numberFormatter
{
  if (_numberFormatter == nil)
  {
    _numberFormatter = [[NSNumberFormatter alloc] init];
    [_numberFormatter setPositiveFormat:@"#,##0.00"];
  }
  return _numberFormatter;
}
</code></pre>

<p>The first time the code to format the table view cell accesses the formatters via the getter method they will be allocated and cached in the instance variables. Note that since we are using ARC we do not need to worry about releasing these objects when the view controller is deallocated.</p>

<p>The table view data source method to return the correctly formatted table cell would like something like this:</p>

<pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  NSNumber *value = [NSNumber numberWithInteger:(indexPath.row+1)*1000];
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
  cell.textLabel.text = [self.numberFormatter stringFromNumber:value];
  cell.detailTextLabel.text = [self.dateFormatter stringFromDate:[NSDate date]];
  return cell;
}
</code></pre>

<p>Note that to keep this example code simple I am generating the data that is displayed from the cell row number and the current date. The actual cell layout is defined using a <a href="http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html">prototype table cell and storyboard</a>.</p>

<h3>Locale Changes</h3>

<p>There is one issue with caching the date and number formatters in this way. The formatters depend on the current user locale when they are created. However if the locale changes the cached formatters will not get updated. This means that if the user changes the locale whilst the app is running, or more likely for an iOS application, whilst it is suspended in the background the number and date formatters will no longer reflect the users locale.</p>

<p>For example, the screenshot of the table view I showed earlier was from the iOS Simulator running with a United Kingdom region format. If I change the region format (Settings > General > International > Region Format) to French-France I might expect to see the following:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-09-002.png" alt="cell format fr" /></p>

<p>Unfortunately as currently implemented the only way the table view will reflect the changed locale is if I force the application to restart. You might not consider this to be a huge problem, after all how often does a user change the locale of their device? On the other hand it takes just a few lines of code to correct and will avoid surprising/annoying a user who does change the locale whilst your app is sleeping peacefully in the background.</p>

<p>You can easily detect that the user has change the locale by registering an observer for the NSCurrentLocaleDidChangeNotification notification. A good place to do that is in the viewDidLoad method of the view controller:</p>

<pre><code>- (void)viewDidLoad
{
  [[NSNotificationCenter defaultCenter] addObserver:self
                      selector:@selector(localeDidChange)
                          name:NSCurrentLocaleDidChangeNotification 
                        object:nil];
}
</code></pre>

<p>We should also ensure that we remove the observer when the view controller is deallocated. In this simple case since we are using ARC this is the only action in our dealloc method:</p>

<pre><code>- (void)dealloc
{
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}
</code></pre>

<p>When our view controller receives the notification the localeDidChange method that we registered can simply remove the number and date formatters by setting them to nil and request the table view to reload:</p>

<pre><code>- (void)localeDidChange
{
  self.numberFormatter = nil;
  self.dateFormatter = nil;
  [self.tableView reloadData];
}
</code></pre>

<p>Since we use lazy initialisation to create the formatters they will then be recreated with the new locale as part of the table view being reloaded. The user will then immediately see the number and date correctly formatted in the current locale without having to restart the app.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/07/09/formatters-and-locale-changes.html">Formatters and Locale Changes</a> was originally posted 09 Jul 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Customizing Appearance With Resizable Images]]></title>
    
      <category term="Appearance"/>
    
    <link href="http://useyourloaf.com/blog/2012/07/05/customizing-appearance-with-resizable-images.html"/>
    <updated>2012-07-05T20:35:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/07/05/customizing-appearance-with-resizable-images</id>
    <content type="html"><![CDATA[<p>Prior to iOS 5 it was not easy to style the appearance of common UIKit controls such as the navigation bar or the tab bar. It could be done but you had to resort to subclassing or create your own custom replacements. With iOS 5, Apple added instance methods to many user interface elements to allow the appearance to be directly customised. They also introduced the UIAppearance protocol to allow the styling or theming of all instances of a class. A detailed discussion of UIAppearance is a subject for a future post. In this post I want to explore the way you can use resizable images when setting background images for classes such as the navigation bar.</p>

<h3>Applying a Tint</h3>

<p>The ability to set a tint color has been present in many, but not all, user interface elements going back to iOS 2.0. With iOS 5 Apple added the tintColor property to more items such as the UITabBar and UIButton. When the tintColor exists it provides a quick and easy way to customise the colour. For example, in the case of a UINavigationBar you might set the tint color in the application delegate as follows:</p>

<pre><code>UINavigationController *navController = (UINavigationController *)self.window.rootViewController;    
UINavigationBar *navBar = navController.navigationBar;
navBar.tintColor = [UIColor orangeColor];
</code></pre>

<p>The system automatically applies a gradient effect to the tint color when displaying the navigation bar:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-05-001.png" alt="Nav Bar Tint Color" /></p>

<h3>Using a Background Image</h3>

<p>When setting the tint color is insufficient you can use a background image to apply textures or other designs to many of the iOS user interface elements. For the rest of this post I am going to limit the discussion to the navigation bar for simplicity but the discussion and technique is applicable to many interface elements in iOS 5.</p>

<p>On a standard, non-retina, iPhone device the navigation bar in portrait mode will have dimensions of 320 pixels wide by 44 pixels high. However most of the time you do not want to create a background image of those dimensions.</p>

<p>As well as being wasteful of system memory and performance you also have the issue of the image being stretched when the device is rotated or when you want to reuse the image for the iPad version of the App. Creating separate images for all variations of device, orientation and retina display would be a pain and luckily is unnecessary.</p>

<h3>Setting A Solid Colour Using A 1x1 Pixel Image</h3>

<p>If all you want is to set the background to a solid colour you actually only need to create a 1x1 pixel image. The system will take care of tiling the image horizontally and vertically to fill the background area of the UI element. I should add the caveat that we actually will also need a 2x2 pixel version of the image to allow for the double resolution retina display.</p>

<p>So with two image files as follows both containing solid orange pixels of the specified dimensions:</p>

<ul>
<li>orange.png - dimensions 1x1 pixels</li>
<li>orange@2x.png - dimensions 2x2 pixels</li>
</ul>


<p>The background image of the navigation bar can be set as follows:</p>

<pre><code>UIImage *navBarImage = [UIImage imageNamed:@"orange"];
[navBar setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];
[navBar setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsLandscapePhone];
</code></pre>

<p>Since the navigation bar has different heights when rotated we need to set the background image for each orientation. The method -setBackgroundImage:forBarMetrics: takes an enumerated type (UIBarMetrics) which has two possible values as follows:</p>

<ul>
<li>UIBarMetricsDefault - the default bar metric.</li>
<li>UIBarMetricsLandscapePhone - landscape iPhone bar metrics</li>
</ul>


<p>Note that on an iPad the navigation bar is always 44 pixels (non retina display) regardless of the device orientation so is covered by the UIBarMetricsDefault option.</p>

<p>The resulting navigation bar is shown below. The difference is subtle but if you compare it to the previous image using just a tint colour you should see that this time there is no gradient effect.</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-05-002.png" alt="Nav Bar Solid Color" /></p>

<h3>Using A 1 Pixel Wide Image With A Gradient</h3>

<p>To apply our own gradient effect to the background image we need image files that are 1 pixel wide but with a height that matches the UI element background. The image in this case will only need to be tiled horizontally to fill the background image area of the navigation bar. For the standard navigation bar we can therefore create the following images containing our own custom gradient:</p>

<ul>
<li>gradient-orange.png - dimensions 1x44 pixels</li>
<li>gradient-orange@2x.png - dimensions 2x88 pixels</li>
<li>gradient-orange-landscape.png - dimensions 1x17 pixels</li>
<li>gradient-orange-landscape.png - dimensions 2x34 pixels</li>
</ul>


<p>Note that this time we do need to take into account the thinner navigation bar on an iPhone in landscape orientation. This has a height dimension of 17 pixels on a standard display and 34 pixels on a retina display.</p>

<p>The code to set the background images in this case is similar to before except that we now have different images for the two bar metrics:</p>

<pre><code>UIImage *navBarImage = [UIImage imageNamed:@"gradient-orange"];
UIImage *navBarLandscapeImage = [UIImage imageNamed:@"gradient-orange-landscape"];
[navBar setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];
[navBar setBackgroundImage:navBarLandscapeImage forBarMetrics:UIBarMetricsLandscapePhone];
</code></pre>

<p>The appearance of the navigation bar in portrait orientation with our own custom gradient is now as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-05-003.png" alt="Nav Bar Gradient" /></p>

<h3>Using End Caps</h3>

<p>So far the differences in the navigation bar appearance have been subtle but this technique really becomes useful when you want to apply end caps to the background image. An end cap is used when for example you want to have a button with rounded corners. Another (bad?) example might be to apply some of fake stitching effects to the edges of the toolbar.</p>

<p>The end caps as the name implies define the area of an image that is not resized when the image is stretched or tiled to fill an area. To illustrate the concept consider an image with two end caps that contain a stitching effect as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-05-004.png" alt="End Caps" /></p>

<p>The end caps are each 8 pixels wide and are separated by an image section that is one pixel wide similar to the image used in the previous gradient example. This makes the image a total of 17 pixels wide. The height of the image is 44 pixels in this case to match our standard navigation bar. When this image is used to set the background of a navigation bar we want the central 1 pixel section to be tiled to fit but the cap ends should not be resized.</p>

<p>The UIImage instance method -resizableImageWithCapInsets: was introduced in iOS 5 and allows us to add cap ends to any existing UIImage. The caps are defined using an UIEdgeInsets structure which specifies the top, left, bottom and right insets to apply to our original image. In this case we can define our two end caps by insetting the existing image from the left and right edges by 8 pixels. So assuming our original 17x44 pixel image is named navbar.png we can create an image with two 8 pixel wide end caps as follows:</p>

<pre><code>UIImage *navBarImage = [UIImage imageNamed:@"navbar"];
navBarImage = [navBarImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 8.0, 0.0, 8.0)];
</code></pre>

<p>Note that in this case we only have two end caps so we specify 0.0 for the top and bottom insets. The image files we need to cover the retina and landscape variations are described below:</p>

<ul>
<li>navbar.png - dimensions 17x44 pixels</li>
<li>navbar@2x.png - dimensions 34x88 pixels</li>
<li>navbar-landscape.png - dimensions 17x32 pixels</li>
<li>navbar-landscape@2x.png - dimensions 34x64 pixels</li>
</ul>


<p>I will not show each image but for example here is the actual navbar@2x.png image that I will use:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-05-006.png" alt="navbar image" /></p>

<p>The code to create the stitched navigation bar for both sizes of the bar is as follows:</p>

<pre><code>UIImage *navBarImage = [UIImage imageNamed:@"navbar"];
navBarImage = [navBarImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 8.0, 0.0, 8.0)];

UIImage *navBarLandscapeImage = [UIImage imageNamed:@"navbar-landscape"];
navBarLandscapeImage = [navBarLandscapeImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 8.0, 0.0, 8.0)];

[navBar setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];
[navBar setBackgroundImage:navBarLandscapeImage forBarMetrics:UIBarMetricsLandscapePhone];
</code></pre>

<p>The final result is shown below. I hope it is unnecessary to state the obvious but just in case I am not claiming this is a good design for a navigation bar&#8230;</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-07-05-005.png" alt="Stitched Nav Bar" /></p>

<h3>Wrapping Up</h3>

<p>As I mentioned previously this technique of resizing images can be applied when setting the images used by many of the standard UIKit user interface elements. For the navigation bar example the images are only resized horizontally but you can also resize vertically if required. Just remember that if you have a repeating pattern you will need to create the image with dimensions that match the area you want to be tiled.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/07/05/customizing-appearance-with-resizable-images.html">Customizing Appearance With Resizable Images</a> was originally posted 05 Jul 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Storyboard Segues]]></title>
    
      <category term="storyboard"/>
    
    <link href="http://useyourloaf.com/blog/2012/06/21/storyboard-segues.html"/>
    <updated>2012-06-21T11:26:00+01:00</updated>
    <id>http://useyourloaf.com/blog/2012/06/21/storyboard-segues</id>
    <content type="html"><![CDATA[<p>I have previously posted on some of the pros and cons of adopting various storyboard features in an existing App. In writing the post on <a href="http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html">prototype table cells</a> it occurred to me that I have said nothing about one of the key features of storyboards - segues. Using storyboard terminology a segue is the transition between scenes (views). In this post I want to compare using a storyboard segue with a traditional view transition.</p>

<h3>Classic View Transitions</h3>

<p>For the purposes of comparison I am first going to add a classic, non-storyboard, transition to the WorldFacts App I used for demonstrating prototype table view cells. To recap we have a table view that shows country data stored in a core data model. The root view is shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-06-06-001.png" alt="WorldFacts Example App" /></p>

<p>What I want to do is add a view transition for when a row is selected in the table that transitions to a detailed country view controller. The detailed country view should end up looking as follows:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-06-21-001.png" alt="WorldFacts Country Detail" /></p>

<p>This is a classic iOS design pattern so I will cover it quickly. First of all I will create a NIB file (<code>UYLCountryViewController.xib</code>) to contain the view and a corresponding view controller (<code>UYLCountryViewController</code>). The view controller is pretty simple, it has a single public property to contain the Country object that it is supposed to display:</p>

<pre><code>@interface UYLCountryViewController : UIViewController
@property (nonatomic, strong) Country *country;
@end
</code></pre>

<p>I will not bother to show the implementation as it is mostly just setting the label text for each element in the viewDidLoad method. Check out the example project code if you are interested in the details.</p>

<p>Now the standard iOS pattern for a view transition from a table view consists of implementing the UITableViewDelegate method <code>tableView:didSelectRowAtIndexPath:</code>:</p>

<pre><code>- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  Country *country = [self.fetchedResultsController objectAtIndexPath:indexPath];
  UYLCountryViewController *viewController = [[UYLCountryViewController alloc] 
                            initWithNibName:@"UYLCountryViewController" bundle:nil];
  viewController.country = country;
  [self.navigationController pushViewController:viewController animated:YES];
}
</code></pre>

<p>The basic steps for a table row view transition can be summarised as follows:</p>

<ul>
<li>Using the indexPath of the selected table row find the corresponding object.</li>
<li>Allocate the detail view controller and initialise it from the NIB file.</li>
<li>Pass the selected object to the detail view controller</li>
<li>Push the view controller onto the navigation stack</li>
</ul>


<p>The code directly related to the view transition is contained in a single method with four lines of code. No big deal but worth keeping in mind when we implement the same functionality using storyboards.</p>

<h3>Storyboard Seque</h3>

<p>To implement the table view transition with storyboards we first need to drag a standard view controller into our country storyboard (refer back to the post on <a href="http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html">prototype table cells</a> for the creation of the storyboard). The configuration of the view controller follows the same steps as for the standalone NIB implementation. We set the class of the controller to be UYLCountryViewController and add and connect the UILabel outlets.</p>

<p>To create the segue/transition you control-drag from the table view cell to the destination view controller and when prompted select the style of the transition (push, modal or custom). In this case we want a standard navigation style push transition. The storyboard should at this point look as shown below:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-06-21-002.png" alt="country.storyboard" /></p>

<p>To complete the storyboard we should set an identifier for the seque using the identity inspector:</p>

<p><img src="http://useyourloaf.com/assets/images/2012/2012-06-21-003.png" alt="segue identifier" /></p>

<p>Now to actually implement the segue view transition from the table view controller we no longer implement the UITableViewDelegate method (<code>tableView:didSelectRowAtIndexPath:</code>). A big difference to the classic approach we saw earlier is that with storyboard segues we no longer need to create the destination view controller or initiate the push transition ourselves. The storyboard takes care of all of that boilerplate code for us. However since we need to pass some data to the destination view controller (in this case the country object to be displayed) we need to implement <code>prepareForSegue:sender:</code>:</p>

<pre><code>- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{ 
  if ([segue.identifier isEqualToString:UYLSegueShowCountry])
  {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
    Country *country = [self.fetchedResultsController objectAtIndexPath:indexPath];        
    UYLCountryViewController *viewController = segue.destinationViewController;
    viewController.country = country;
  }
}
</code></pre>

<p>In this simple example our view controller only has a single segue from a table view cell. The segue argument is an object of class UIStoryboardSegue which we can use to both check for the seque identifier we set in the storyboard and also to obtain a reference to the destination view controller that we need to configure.</p>

<p>It is not strictly necessary for us to set and check for the segue identifier in this case as we have only one. In more complicated scenarios with multiple segues triggered from multiple sources we can use the segue and sender arguments to differentiate.</p>

<p>The sender argument in this case is a reference to the UITableViewCell that the user selected to trigger the segue. We need to get the country object that corresponds to the selected table view cell so that we can pass it to the destination country view controller. This requires two-steps, the first to ask the table view for the NSIndexPath that corresponds to the source table view cell. Once we have the index path we can then get the country object as before using the fetched results controller. We can then retrieve the destination view controller from UIStoryboardSegue object and pass it the country object. The storyboard takes care of everything else for us.</p>

<h3>Wrapping Up</h3>

<p>If we compare this storyboard approach with the previous non-storyboard version there is not much in the way of code saving. We avoid having to create and push the destination view controller but in the end it still takes us about the same amount of code to configure it. In more complex scenarios the need to check a long list of segue identifiers to determine which destination view controller we need to configure can also start to look a little ugly.</p>

<p>Whilst there is not much in the way of code saving with segues the advantage is that you do get to see the way your interface flows in the storyboard. That may not be a big enough advantage to make you want to leap into using storyboards everywhere in your app but it helps. I should of course also mention the obvious constraint that storyboards are an iOS 5 (and now iOS 6) feature.</p>

<p>As always the example Xcode project can be found in my <a href="https://github.com/kharrison/CodeExamples">CodeExamples GitHub repository</a> if you want to check the details for yourself. I have left the original NIB files in the project for comparison even though they are no longer required.</p>

      <hr><p><a href="http://useyourloaf.com/blog/2012/06/21/storyboard-segues.html">Storyboard Segues</a> was originally posted 21 Jun 2012 on <a href="http://useyourloaf.com">http://useyourloaf.com</a>. Copyright 2013 Keith Harrison.</p>]]></content>
  </entry>
  
</feed>
