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

<channel>
	<title>The Carbon Emitter &#187; objective-c</title>
	<atom:link href="http://blog.carbonfive.com/tag/objective-c/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.carbonfive.com</link>
	<description>The blog of Carbon Five</description>
	<lastBuildDate>Thu, 19 Apr 2012 16:48:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Customizing the iOS keyboard</title>
		<link>http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/</link>
		<comments>http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 06:20:29 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[objective-c]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=6068</guid>
		<description><![CDATA[Our applications need input and the default iOS keyboards are often not optimally suited to providing the sort of data we want. When we find that we really wish the keyboard had some extra controls or want to help our &#8230; <a href="http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Our applications need input and the default iOS keyboards are often not optimally suited to providing the sort of data we want. When we find that we really wish the keyboard had some extra controls or want to help our users enter a specific set of symbols it is time to customize our apps&#8217; keyboards.</p>

<span id="more-6068"></span>

<p><strong>What controls the keyboard anyway?</strong></p>

<p>Our first exposure to different keyboard types probably comes from <code>UITextField</code> and <code>UITextView</code>. Both provide conform to the <code>UITextInputTraits</code> protocol which gives us options to set the keyboard type, return key type, keyboard appearance, and other behaviors. Those options cover many of the types of text input we might want to support; plain text, passwords, email addresses, urls, and so on. That&#8217;s a good place to start customizing our keyboard options but <code>UITextInputTraits</code> itself doesn&#8217;t present the keyboard so when we need behavior the protocol doesn&#8217;t provide we will have to keep looking.</p>

<p>Traversing up the class hierarchy we see that <code>UITextField</code>, <code>UITextView</code>, and indeed all <code>UIView</code> objects inherit from <code>UIResponer</code>. All of the responder objects in our views form a responder chain, a sequence of objects which will be given a chance to respond to non-touch input events. (If this isn&#8217;t a familiar topic then take a look at &#8220;Responder Objects and the Responder Chain&#8221; in the &#8220;Event Handling Guide for iOS&#8221; for a full discussion of how the system works.)  Whenever a responder becomes the first responder (see <code>-becomeFirstResponer</code>) it determines what, if any, keyboard needs to be shown.
<code>UIResponder</code> gives us two read-only properties for controlling the keyboard&#8217;s appearance; <code>inputView</code> which provides the keyboard itself and <code>inputAccessoryView</code> which controls the accessory view attached to the top of the keyboard (containing the &#8220;next&#8221; and &#8220;previous&#8221; buttons when editing a form in Mobile Safari for example). By returning our own views from these properties we can replace the system keyboards with any custom <code>UIView</code> we care to construct.</p>

<p><strong>Start simple: customizing UITextView</strong></p>

<p><code>UITextField</code> (and <code>UITextView</code>) redefine their <code>inputView</code> and <code>inputAccessoryView</code> properties to be <code>readwrite</code> instead of <code>readonly</code>. When working with these view classes we can therefore set their keyboard easily from some other class, like our view controller.</p>

<p>Suppose we were want to support editing <a href="http://daringfireball.net/projects/markdown/">markdown</a> formatted text in our app. The system keyboards work well for this but it takes three taps to enter a # or * and &#92; doesn&#8217;t appear on the keyboard at all. That&#8217;s going to make it difficult for our users to emphasize text or insert code blocks. Let&#8217;s add an input accessory view to give them &#8220;emphasize&#8221;, &#8220;strong&#8221;, and &#8220;code&#8221; formatting controls.</p>

<p>Given a simple view controller with <code>UITextView *textView</code> and <code>UIView *accessoryView</code> outlets we can set the text view&#8217;s <code>inputAccessoryView</code> in our <code>-viewDidLoad</code>.</p>

<pre><code><pre class="brush: objc; title: ; notranslate">@interface MarkdownViewController : UIViewController

@property (nonatomic, strong) IBOutlet UITextView *textView;
@property (nonatomic, strong) IBOutlet UIView *accessoryView;

@end

@implementation MarkdownViewController

@synthesize textView;
@synthesize accessoryView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.textView.inputAccessoryView = self.accessoryView;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.textView = nil;
    self.accessoryView = nil;
}

@end</pre>
</code></pre>

<p>Now when the text view becomes the first responder we see our accessory view added to the top of the keyboard.</p>

<p><a href="http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/screen-shot-2012-03-12-at-11-16-31-pm/" rel="attachment wp-att-6071"><img src="http://blog.carbonfive.com/wp-content/uploads/2012/03/Screen-Shot-2012-03-12-at-11.16.31-PM.png" alt="" title="Screen Shot 2012-03-12 at 11.16.31 PM" width="396" height="744" class="alignright size-full wp-image-6071" /></a></p>

<p><strong>Responding to input</strong></p>

<p>Showing our accessory view is only half of the solution. We also want to make changes to our text view&#8217;s content when a user taps one of the accessory view&#8217;s buttons. Let&#8217;s create a custom view class for our accessory view and give it a reference to the text field.</p>

<pre><code><pre class="brush: objc; title: ; notranslate">@interface MarkdownInputAccessoryView : UIView

@property(nonatomic, weak) id &amp;lt;UITextInput&amp;gt; delegate;

- (IBAction)toggleStrong:(id)sender;
- (IBAction)toggleEmphasis:(id)sender;
- (IBAction)toggleCode:(id)sender;

@end

@implementation MarkdownInputAccessoryView

@synthesize delegate;

- (IBAction)toggleStrong:(id)sender {
    UITextRange *selectedText = [delegate selectedTextRange];
    if (selectedText == nil) {
        //no selection or insertion point
        //...
    }
    else if (selectedText.empty) {
        //inserting text at an insertion point
        [delegate replaceRange:selectedText withText:@&amp;quot;*&amp;quot;];
        //...
    }
    else {
        //updated a selected range
        //...
    }
}

- (IBAction)toggleEmphasis:(id)sender {
    //...
}

- (IBAction)toggleCode:(id)sender {
    //...
}

@end</pre>
</code></pre>

<p>Our controller can then set the delegate property and the accessory view will be able to update the text field.</p>

<pre><code><pre class="brush: objc; title: ; notranslate">//...
@property (nonatomic, strong) IBOutlet UIView *accessoryView;
//...
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.accessoryView.delegate = self.textView;
    self.textView.inputAccessoryView = self.accessoryView;
}</pre>
</code></pre>

<p><strong>Adding complexity: keyboards for a custom UIView</strong></p>

<p>Adding a custom input view is much the same as adding a custom input accessory view. When we&#8217;re working with a <code>UITextField</code> or <code>UITextView</code> we can create the custom view and pass it to the appropriate property&#8217;s setter.If however we have built a custom <code>UIView</code> subclass then we have to do a little more work.</p>

<p>If it still makes sense for a view controller or other class to provide the view with its input views then we can redeclare <code>inputView</code> and <code>inputAccessoryView</code> as <code>readwrite</code> properties, exposing setters so that the view can be given references to the input views it should use. Alternately we can override the <code>inputView</code> and <code>inputAccessoryView</code> getter methods to return appropriate views. I tend to prefer the latter option because it allows a view to how its own input controls should be presented but if selecting an appropriate input view depends on factors like the current interface idiom or language then it may make more sense for an external service to provide an input view for the current view.</p>

<p>If we wanted to build a view for displaying a score of sheet music we might build something like the following.</p>

<pre><code><pre class="brush: objc; title: ; notranslate">@class MusicScoreView;

@interface MusicScoreInputView : UIView

@property (nonatomic, weak) IBOutlet MusicScoreView *delegate;

@end

@interface MusicScoreView ()

@property(nonatomic, readwrite, strong) IBOutlet UIView *inputView;

- (void) loadInputView;

@end

@implementation MusicScoreView

@synthesize inputView;

- (id)initWithFrame:(CGRect)frame {
    self = [super init];
    if (self) {
        [self loadInputView];
    }
    return self;    
}

- (id)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self loadInputView];
    }
    return self;
}

- (void)loadInputView {
    UINib *inputViewNib = [UINib nibWithNibName:@&amp;quot;MusicScoreInputView&amp;quot; bundle:nil];
    [inputViewNib instantiateWithOwner:self options:nil];
}

@end

@interface MusicScoreInputView : UIView

@property (nonatomic, weak) IBOutlet MusicScoreView *delegate;

@end

@implementation MusicScoreInputView

@synthesize delegate;

@end</pre>
</code></pre>

<p><a href="http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/screen-shot-2012-03-12-at-11-16-15-pm/" rel="attachment wp-att-6074"><img src="http://blog.carbonfive.com/wp-content/uploads/2012/03/Screen-Shot-2012-03-12-at-11.16.15-PM.png" alt="" title="Screen Shot 2012-03-12 at 11.16.15 PM" width="396" height="744" class="alignright size-full wp-image-6074" /></a></p>

<p><strong>Visual styling: reacting to the keyboard</strong></p>

<p>Now that we can display a custom keyboard we still need to make sure to adjust our views when it appears. Since the actual presentation of our input view is handled by UIKit we need to observe and react to the notifications the framework sends to announce changes in the input view&#8217;s position. Apple provides a set of <code>NSNotification</code>s we can observe:</p>

<ul>
    <li><code>UIKeyboardWillShowNotification</code></li>
    <li><code>UIKeyboardDidShowNotification</code></li>
    <li><code>UIKeyboardWillHideNotification</code></li>
    <li><code>UIKeyboardDidHideNotification</code></li>
</ul>

<p>Each of these notifications includes a user info dictionary which describes the frame of the keyboard before and after its transition and the timing of the animation which will be used to show or hide it. When we rotate a device the keyboard may be resized to better support the new orientation. In that case we&#8217;ll need to update the insets or positions of our other views as well to reflect these new dimensions. Again UIKit provides a set of notifications we can observe to determine the changing bounds of the keyboard and react accordingly.</p>

<ul>
    <li><code>UIKeyboardWillChangeFrameNotification</code></li>
    <li><code>UIKeyboardDidChangeFrameNotification</code></li>
</ul>

<p>Given these we can respond to the appearance or disappearance of the keyboard as needed.</p>

<pre><code><pre class="brush: objc; title: ; notranslate">- (void)viewWillAppear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateScrollInsets:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateScrollInsets:) name:UIKeyboardWillChangeFrameNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resetScrollInsets:) name:UIKeyboardWillHideNotification object:nil];
}

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

<p>In most cases we will want to respond by adjusting the <code>contentInset</code> and <code>scrollIndicatorInsets</code> of a <code>UIScrollView</code> to add enough padding to the bottom of our scroll view&#8217;s content view that all of its content can scroll to a position above the top of the keyboard. Alternately we might adjust the frames of some of our views directly but this is less desirable because it might leave a blank region on the screen (rather than showing the scroll view&#8217;s background color), especially on an iPad where the user can choose to split the keyboard.</p>

<p>To calculate the appropriate insets we need to be aware that the keyboard is presented anchored to the bottom of the window, which is not necessarily flush with the bottom of the current view controller&#8217;s view (for example we might have a tab bar or tool bar visible). We should only add insets equal to the height of the portion of our view which is being hidden by the keyboard.</p>

<pre><code><pre class="brush: objc; title: ; notranslate">- (void) updateScrollInsets:(NSNotification *)notification {
    //determine what portion of the view will be hidden by the keyboard
    CGRect keyboardEndFrameInScreenCoordinates;
    [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&amp;amp;keyboardEndFrameInScreenCoordinates];
    CGRect keyboardEndFrameInWindowCoordinates = [self.view.window convertRect:keyboardEndFrameInScreenCoordinates fromWindow:nil];
    CGRect keyboardEndFrameInViewCoordinates = [self.view convertRect:keyboardEndFrameInWindowCoordinates fromView:nil];
    CGRect windowFrameInViewCoords = [self.view convertRect:self.view.window.frame fromView:nil];
    CGFloat heightBelowViewInWindow = windowFrameInViewCoords.origin.y + windowFrameInViewCoords.size.height - (self.view.frame.origin.y + self.view.frame.size.height);
    CGFloat heightCoveredByKeyboard = keyboardEndFrameInViewCoordinates.size.height - heightBelowViewInWindow;

    //build an inset to add padding to the content view equal to the height of the portion of the view hidden by the keyboard
    UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, heightCoveredByKeyboard, 0);
    [self setInsets:insets givenUserInfo:notification.userInfo];
}

- (void) resetScrollInsets:(NSNotification *)notification {
    UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, 0, 0);
    [self setInsets:insets givenUserInfo:notification.userInfo];
}

- (void) setInsets:(UIEdgeInsets)insets givenUserInfo:(NSDictionary *)userInfo {
    //match the keyboard's animation
    double duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
    UIViewAnimationOptions animationOptions = animationCurve;
    [UIView animateWithDuration:duration delay:0 options:animationOptions animations:^{
        self.textView.contentInset = insets;
        self.textView.scrollIndicatorInsets = insets;
    } completion:nil];
}</pre>
</code></pre>

<p><a href="http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/screen-shot-2012-03-12-at-11-16-04-pm/" rel="attachment wp-att-6075"><img src="http://blog.carbonfive.com/wp-content/uploads/2012/03/Screen-Shot-2012-03-12-at-11.16.04-PM.png" alt="" title="Screen Shot 2012-03-12 at 11.16.04 PM" width="396" height="744" class="alignleft size-full wp-image-6075" /></a></p>

<p><a href="http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/screen-shot-2012-03-12-at-11-16-08-pm/" rel="attachment wp-att-6076"><img src="http://blog.carbonfive.com/wp-content/uploads/2012/03/Screen-Shot-2012-03-12-at-11.16.08-PM.png" alt="" title="Screen Shot 2012-03-12 at 11.16.08 PM" width="744" height="396" class="alignright size-full wp-image-6076" /></a></p>

<p><strong>Summary</strong></p>

<p>We&#8217;ve seen how to define custom input and input accessory views to enhance or replace the system keyboard. How to add those input views to existing text fields, text views, and to our own custom view classes. When an input view does appear we can also now appropriately adjust the rest of our content to accommodate it. With these tools we should now be ready to build custom input views tailored to the type of data we need and the context in which it will be gathered.</p>

<p>The examples given above are also available at <a href="https://jonah-carbonfive@github.com/jonah-carbonfive/CustomInputViewDemo.git">https://jonah-carbonfive@github.com/jonah-carbonfive/CustomInputViewDemo.git</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Monkey-Patching iOS with Objective-C Categories Part I: Simple Extensions and Overrides</title>
		<link>http://blog.carbonfive.com/2012/01/23/monkey-patching-ios-with-objective-c-categories-part-1-simple-extensions-and-overrides/</link>
		<comments>http://blog.carbonfive.com/2012/01/23/monkey-patching-ios-with-objective-c-categories-part-1-simple-extensions-and-overrides/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 18:38:45 +0000</pubDate>
		<dc:creator>Rudy Jahchan</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[monkey-patching]]></category>
		<category><![CDATA[objective-c]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=5851</guid>
		<description><![CDATA[Have you ever wanted to introduce new functionality to base classes in the iOS SDK? Or just make them work a little bit differently? In order to do so, you must enter the wild and dangerous world of monkey-patching. Monkey-patching &#8230; <a href="http://blog.carbonfive.com/2012/01/23/monkey-patching-ios-with-objective-c-categories-part-1-simple-extensions-and-overrides/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Have you ever wanted to introduce new functionality to base classes in the iOS SDK? Or just make them work a <strong>little bit</strong> differently? In order to do so, you must enter the wild and dangerous world of monkey-patching.</p>

<p>Monkey-patching is extending or modifying the behavior of code at runtime <strong>without</strong> changing its original source code. You can monkey-patch any code, it doesn&#8217;t matter whether it&#8217;s your own code or not. This is distinctly different than traditional sub-classing because you are not creating a new class, instead, you are reopening an existing class and changing its behavior.</p>

<p>Monkey-patching is possible in Objective-C by using <a href="http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html">categories</a>. In fact, the definition of a category practically matches that of monkey-patching:</p>

<p><code>"A category allows you to add methods to an existing class—even to one for which you do not have the source."</code></p>

<p>In this series of posts, we&#8217;ll use categories to add and change methods, to add new instance variables and properties, and introduce swizzling, a technique that allows us to extend and preserve existing functionality.<span id="more-5851"></span> <a href="#tldr"><strong>TL;DR &raquo;</strong></a></p>

<h2>Category Basics</h2>

<p>To modify an existing class specify the category in both its interface and implementation definitions:</p>

<h4>Interface Definition</h4>

<script src="https://gist.github.com/1660134.js?file=AClassACategoryImplementation.h"></script>

<h4>Implementation</h4>

<script src="https://gist.github.com/1660134.js?file=AClassACategoryImplementation.m"></script>

<h2>Adding Simple Methods</h2>

<p>The most basic usage of categories is to add a new method to an existing class.</p>

<p>Suppose in our application we want to output dates relative to the current time, e.g., &#8220;13 minutes ago&#8221;, &#8220;4 hours ago&#8221;, &#8220;just now&#8221;, etc. Traditional object-oriented solutions would have us introducing a new class that either extends <code>NSDate</code> (e.g., creating a <code>RelativeDescriptionDate</code> subclass with a <code>timeAgoInWords</code> instance method) or is a standalone helper/utility class (e.g., <code>[NSDateHelper timeAgoInWordsFromDate:myDate]</code>).</p>

<p>But with categories, we can reopen the <code>NSDate</code> class and simply add a new instance method:</p>

<h4>NSDate+Formatting.h</h4>

<script src="https://gist.github.com/1660134.js?file=NSDateFormatting.h"></script>

<h4>NSDate+Formatting.m</h4>

<script src="https://gist.github.com/1660134.js?file=NSDateFormatting.m"></script>

<p>Now <strong>every</strong> <code>NSDate</code> object will have the new method available to it. The following code:</p>

<script src="https://gist.github.com/1660134.js?file=UsingNSDateFormatting.m"></script>

<p>Will print out the following on the console:</p>

<script src="https://gist.github.com/1660134.js?file=gistfile1.sh"></script>

<h2>The Dangers of Simply Overriding Methods</h2>

<p>We can take this a step further and instead of adding new behavior we&#8217;ll override existing behavior. Continuing with our example, what if we wanted the default description of a <code>NSDate</code> object to include the time ago in words? We could simply do the following:</p>

<script src="https://gist.github.com/1660134.js?file=NSDateFormatting2.m"></script>

<p>However, this is <strong>strongly discouraged</strong> for two reasons.</p>

<ol>
<li>Other frameworks may rely on the expected behavior of the original method. We now have to go through the trouble of re-implementing that behavior, in addition to the new functionality we wanted to introduce, or risk strange side effects and possibly even crashing out. </li>
<li>If multiple categories implement the same method, the last one loaded wins! The load order is consistent within an application, but it&#8217;s arbitrary, out of our hands, and fragile. For all we know, our implementation could itself be overwritten by an internal framework category!</li>
</ol>

<p>Because of these reasons, this blunt approach to overriding methods should only be used for the simplest of cases. Later in this series, we&#8217;ll explore how swizzling allows us to override a method while preserving all implementations.</p>

<h2>Including Your Monkey-Patches</h2>

<p>Categories are not automatically &#8220;picked up&#8221; in a project. Any code that relies on the behavior will need to <code>#import</code> the necessary header files:</p>

<script src="https://gist.github.com/1660134.js?file=EntryCell.m"></script>

<p>However, including the same set of headers over and over again is redundant. We should first create a single header file that imports all of our most frequently used categories:</p>

<script src="https://gist.github.com/1660134.js?file=Extensions.h"></script>

<p>We can then import this single header file into a prefix header that is added to all source files. XCode projects often have a <code>.pch</code> file in the Supporting Files group for this very purpose.</p>

<script src="https://gist.github.com/1660134.js?file=pc.h"></script>

<h2>Next Up</h2>

<p>While adding and overriding classes is straightforward, there is one very big caveat when using Categories; you <strong>cannot add new instance variables</strong> to a class. We&#8217;ll take a look at working around this limitation in the next post.</p>

<h2><a name="tldr"></a> tl;dr</h2>

<ul>
<li>Use Objective-C categories to add functionality to existing classes without subclassing.</li>
<li>Avoid simple overrides with categories as it can cause problems with other frameworks.</li>
<li>Use prefix headers to easily import your extensions.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2012/01/23/monkey-patching-ios-with-objective-c-categories-part-1-simple-extensions-and-overrides/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Managing iOS Configurations per Environment in Xcode 4</title>
		<link>http://blog.carbonfive.com/2011/06/20/managing-ios-configurations-per-environment-in-xcode-4/</link>
		<comments>http://blog.carbonfive.com/2011/06/20/managing-ios-configurations-per-environment-in-xcode-4/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 10:16:34 +0000</pubDate>
		<dc:creator>Rob Pak</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=3545</guid>
		<description><![CDATA[At Carbon Five we usually have 3 &#8211; 4 environments our iOS applications will run against: development, acceptance, staging and production. Often, the property values that are unique across environments are URLs to APIs that we are integrating with. There &#8230; <a href="http://blog.carbonfive.com/2011/06/20/managing-ios-configurations-per-environment-in-xcode-4/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At Carbon Five we usually have 3 &#8211; 4 environments our iOS applications will run against: development, acceptance, staging and production. Often, the property values that are unique across environments are URLs to APIs that we are integrating with. There have been several approaches for managing different configurations per environment. Some have included <a href="http://developer.apple.com/library/ios/#documentation/Xcode/Conceptual/iphone_development/115-Configuring_Applications/configuring_applications.html" target="_">conditional compilation</a> or build-time file substitution. While all are valid approaches, I opted to use Xcode&#8217;s build configurations to manage configurations per environment. Here is how I did it:</p>
<h2>Step 1: Modify Your Default PList File</h2>
<p>Your default plist file is usually named ${PRODUCT_NAME}-Info.plist and is located beneath the &#8220;Supporting Files&#8221; group of your Xcode project. Add a new row/item of type <em>String</em> to the plist file and name it <em>Configuration</em>. Set the value to be <em>${CONFIGURATION}</em>, the Xcode provided environment variable for the current build configuration.</p>
<p><a href="http://blog.carbonfive.com/wp-content/uploads/2011/05/infoplist.png"><img class="size-full wp-image-3555" title="InfoPlist" src="http://blog.carbonfive.com/wp-content/uploads/2011/05/infoplist.png" alt="" width="640" height="330" /></a></p>
<p><span id="more-3545"></span></p>
<h2>Step 2: Create a Custom Environments.plist File to Store Configuration Data</h2>
<p>Right-click on the &#8220;Supporting Files&#8221; group and select &#8220;New File&#8221; (New File &gt; Resource &gt; Property List). Save File as &#8220;Environments&#8221;, this will create a file named &#8220;Environments.plist&#8221;. Now that you have your custom plist file ready to be modified, add all of your build configurations (Debug and Release by default) of type Dictionary to the plist. You can also begin to enter custom properties underneath each build configuration (entered as myAPIURL in my example).</p>
<p>Optionally, you can segregate your property files per build configuration. For example, create plist files for each of your build configurations (i.e. Debug.plist, Release.plist).</p>
<p><a href="http://blog.carbonfive.com/wp-content/uploads/2011/05/environments.png"><img class="alignnone size-full wp-image-3559" title="Environments" src="http://blog.carbonfive.com/wp-content/uploads/2011/05/environments.png" alt="Add Custom Properties to Configuration by Environment (Build Configuration)" width="640" height="274" /></a></p>
<h2>Step 3: Make your Custom Configuration Available to your Application</h2>
<p>Create a singleton or implement a strategy to load your configuration data on a per build configuration basis. You can determine your scheme&#8217;s current build configuration by reading the &#8220;Configuration&#8221; property within your default plist file (as applied in step one).</p>
<p>For example, here is a singleton that will load your configuration:<br />
<script src="https://gist.github.com/1032532.js?file=Environment.m"></script></p>
<p>Now you should be able to access properties within your application by sending getter messages to the Environment instance.</p>
<p><pre class="brush: objc; title: ; notranslate">
Environment *myEnvironment = [Environment sharedInstance];
NSString *apiURL = myEnvironment.myApiURL;
</pre>
</p>
<h2>Step 4: Add Additional Build Configurations to your Application</h2>
<p>Within Xcode, select your Project within the left-hand navigation. Your project and target settings should be visible and editable. Next, select your project settings so that your build configurations are exposed (by default, Xcode creates the Debug and Release build configurations for you). At this point you can create a new build configuration for a custom environment (i.e. acceptance, staging or demo).</p>
<p><a href="http://blog.carbonfive.com/wp-content/uploads/2011/05/project.png"><img class="size-full wp-image-3574" title="project" src="http://blog.carbonfive.com/wp-content/uploads/2011/05/project.png" alt="" width="640" height="286" /></a></p>
<p>
 Also, don&#8217;t forget to add your custom configuration data for your new build configuration.
</p>
<p><a href="http://blog.carbonfive.com/wp-content/uploads/2011/05/acceptance.png"><img class="size-full wp-image-3575" title="acceptance" src="http://blog.carbonfive.com/wp-content/uploads/2011/05/acceptance.png" alt="" width="640" height="220" /></a></p>
<h2>Now Your Ready!</h2>
<p>Your application now has access to configurations per environment by use of build configurations. We&#8217;ve made the current build configuration readable by adding it to the default plist file. We used the current build configuration as an identifier for key&#8217;ing entries in a custom properties file (Environments.plist). The custom properties file contains configuration properties per build configuration. In order to read the custom properties programmatically, we created an object (Environment.m) to read the file. Finally, we added custom build configurations to support new, application specific, environments.</p>
<p>Some side notes:</p>
<ul>
<li>One target, configurable schemes: You can change the build configuration you would like to use for a target by editing (or creating) your scheme. This will quickly allow you to run your target against different application environments.</li>
<li>Properties like bundle identifier and bundle name can be set by user defined properties and further specified by your build configurations. This will make deploying you application to devices easier.</li>
<li>The Xcode command line build tool has a parameter named &#8220;configuration&#8221;. This will allow you to build your application per environment (i.e. xcodebuild -configuration Debug).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/06/20/managing-ios-configurations-per-environment-in-xcode-4/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Debug logging with Xcode 4 breakpoints</title>
		<link>http://blog.carbonfive.com/2011/06/16/debug-logging-with-xcode-4-breakpoints/</link>
		<comments>http://blog.carbonfive.com/2011/06/16/debug-logging-with-xcode-4-breakpoints/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 00:12:04 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=4111</guid>
		<description><![CDATA[NSLog calls do not belong in release builds. Logging is slow and the performance impact of log statements on a device can be considerable. Logging is also noisy, it can obscure useful debugging information and may leak information you would &#8230; <a href="http://blog.carbonfive.com/2011/06/16/debug-logging-with-xcode-4-breakpoints/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>NSLog calls do not belong in release builds. Logging is slow and the performance impact of log statements on a device can be considerable. Logging is also noisy, it can obscure useful debugging information and may leak information you would rather not expose in a release build. Looking at my device&#8217;s system log I see output full of content urls, api keys, massive log messages, and data only valuable while debugging an app.</p>
<blockquote><p>: Succeeded! Received 18977 bytes of data for url http://www&#8230;<br />
: fetched comments: ( &#8230;&lt;74k of JSON&gt;<br />
: *** &#8230;GetData: http://&#8230;/query?id=1001&amp;sc=17&amp;fields=&#8230;&amp;apiKey=<br />
: applicationDidBecomeActive completed<br />
: JSON parsing finished in 24 ms. String alloc took 2 ms. Comment stripping took 1 ms.<br />
: CallbackHandler registered delegate,, instance=0&#215;263650</p></blockquote>
<p>There are a number of examples of using precompiler macros to eliminate log output on non-debug builds but I recently started using Xcode 4&#8242;s breakpoints and find them to be my favorite mechanism. Breakpoints can be configured to log arbitrary output and automatically continue to avoid stopping program execution. They can be dragged from one line to another, added, disabled, and removed while your app is running. You can even check them in as part of your project to share them with other developers.<br />
<span id="more-4111"></span></p>
<p><strong>Console logging with breakpoints</strong><br />
Create a new breakpoint by clicking in the source editor&#8217;s gutter.<br />
Control-click the breakpoint to edit its behavior.<br />
<a rel="attachment wp-att-4113" href="http://blog.carbonfive.com/2011/06/16/debug-logging-with-xcode-4-breakpoints/edit_breakpoint/"><img class="alignnone size-full wp-image-4113" title="edit_breakpoint" src="http://blog.carbonfive.com/wp-content/uploads/2011/06/edit_breakpoint.png" alt="" width="498" height="273" /></a><br />
When hit the example breakpoint above will log <code>-didReceiveMemoryWarning my title is "Demo!"</code> to the console.</p>
<p><strong>Sharing breakpoints</strong><br />
In the breakpoint navigator control-click a breakpoint to share it as part of a workspace.<br />
Shared breakpoints are stored in .xcworkspace/xcshareddata/xcdebugger/Breakpoints.xcbkptlist<br />
<a rel="attachment wp-att-4114" href="http://blog.carbonfive.com/2011/06/16/debug-logging-with-xcode-4-breakpoints/share_breakpoint/"><img class="alignnone size-full wp-image-4114" title="share_breakpoint" src="http://blog.carbonfive.com/wp-content/uploads/2011/06/share_breakpoint.png" alt="" width="457" height="320" /></a><br />
<a rel="attachment wp-att-4115" href="http://blog.carbonfive.com/2011/06/16/debug-logging-with-xcode-4-breakpoints/shared_breakpoint/"><img class="alignnone size-full wp-image-4115" title="shared_breakpoint" src="http://blog.carbonfive.com/wp-content/uploads/2011/06/shared_breakpoint.png" alt="" width="490" height="290" /></a><br />
I&#8217;ve found breakpoints to be a great way to log debug information about the app in a configuration which I can choose to share with my team and which runs no risk of appearing in a release build. The breakpoints navigator gives me an easy way to jump to any of these log statements and it is trivial to switch a breakpoint from just logging to pausing the app so I can debug in depth. I&#8217;ll still use NSLog for exceptional conditions I want to report in any build but so far you won&#8217;t find a single one in my current project.</p>
<p>Have you found a NSLog alternative you are happy with? Is there anything you couldn&#8217;t replace with logging breakpoints instead?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/06/16/debug-logging-with-xcode-4-breakpoints/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Automated ad hoc builds using Xcode 4</title>
		<link>http://blog.carbonfive.com/2011/05/04/automated-ad-hoc-builds-using-xcode-4/</link>
		<comments>http://blog.carbonfive.com/2011/05/04/automated-ad-hoc-builds-using-xcode-4/#comments</comments>
		<pubDate>Wed, 04 May 2011 23:24:19 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[teamcity]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=3521</guid>
		<description><![CDATA[I&#8217;ve previously discussed Continuous Integration for iPhone Projects in TeamCity using Xcode 3 and Building Xcode 4 Projects from the Command Line. Now I&#8217;ll tie those together and use TeamCity to automatically create ad hoc builds I can install over &#8230; <a href="http://blog.carbonfive.com/2011/05/04/automated-ad-hoc-builds-using-xcode-4/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve previously discussed <a href="http://blog.carbonfive.com/2010/08/08/continuous-integration-for-iphone-projects-in-teamcity/">Continuous Integration for iPhone Projects in TeamCity</a> using Xcode 3 and <a href="http://blog.carbonfive.com/2011/04/06/building-xcode-4-projects-from-the-command-line/">Building Xcode 4 Projects from the Command Line</a>. Now I&#8217;ll tie those together and use TeamCity to automatically create ad hoc builds I can install over the air (directly onto a device without using iTunes) every time I check in code.</p>
<p><span id="more-3521"></span></p>
<p>I created a basic project configuration in TeamCity 6 to checkout my iOS project from git.</p>
<p>I set the artifact paths for this configuration to</p>
<blockquote><p>
project_name.acceptance.app*<br />
ad_hoc/*.png
</p></blockquote>
<p>This will eventually allow TeamCity to collect the icons, project_name.acceptance.app.ipa, and project_name.acceptance.app.plist files needed to perform an over the air install of the ad hoc build.</p>
<p>Finally I created the following custom script build step (available as <a href="https://gist.github.com/949831">https://gist.github.com/949831</a>).</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash

# https://gist.github.com/949831
# http://blog.carbonfive.com/2011/05/04/automated-ad-hoc-builds-using-xcode-4/

# command line OTA distribution references and examples
# http://nachbaur.com/blog/how-to-automate-your-iphone-app-builds-with-hudson
# http://nachbaur.com/blog/building-ios-apps-for-over-the-air-adhoc-distribution
# http://blog.octo.com/en/automating-over-the-air-deployment-for-iphone/
# http://www.neat.io/posts/2010/10/27/automated-ota-ios-app-distribution.html

project_dir=`pwd`

# Configuration
environment_name=&quot;staging&quot;
keychain=&quot;ci_keys&quot;
keychain_password=&quot;super secret&quot;
workspace=&quot;MyApp.xcworkspace&quot;
scheme=&quot;Ad Hoc&quot;
info_plist=&quot;$project_dir/MyApp-Info.plist&quot;
environment_plist=&quot;$environment_name.plist&quot;
environment_info_plist=&quot;$environment_name-Info.plist&quot;
product_name=&quot;My App $environment_name&quot;
mobileprovision=&quot;$project_dir/ad_hoc/MyAppStaging.mobileprovision&quot;
provisioning_profile=&quot;iPhone Distribution: My Company, LLC&quot;
build_number=&quot;%env.BUILD_NUMBER%&quot;
artifacts_url=&quot;http://my_ci_server.example/artifacts/$build_number&quot;
display_image_name=&quot;Icon-57.png&quot;
full_size_image_name=&quot;Icon-512.png&quot;

function failed()
{
    local error=${1:-Undefined error}
    echo &quot;Failed: $error&quot; &gt;&amp;2
    exit 1
}

function validate_keychain()
{
  # unlock the keychain containing the provisioning profile's private key and set it as the default keychain
  security unlock-keychain -p &quot;$keychain_password&quot; &quot;$HOME/Library/Keychains/$keychain.keychain&quot;
  security default-keychain -s &quot;$HOME/Library/Keychains/$keychain.keychain&quot;

  #describe the available provisioning profiles
  echo &quot;Available provisioning profiles&quot;
  security find-identity -p codesigning -v

  #verify that the requested provisioning profile can be found
  (security find-certificate -a -c &quot;$provisioning_profile&quot; -Z | grep ^SHA-1) || failed provisioning_profile
}

function describe_sdks()
{
  #list the installed sdks
  echo &quot;Available SDKs&quot;
  xcodebuild -showsdks
}

function describe_workspace()
{
  #describe the project workspace
  echo &quot;Available schemes&quot;
  xcodebuild -list -workspace $workspace
}

function increment_version()
{
  cd &quot;MyApp&quot;
  agvtool -noscm new-version -all $build_number
  cd ..
}

function set_environment()
{
  #copy the info plist for the selected environment into place
  cp -v &quot;MyApp/$environment_info_plist&quot; $info_plist || failed environment_plist
  #copy the environment settings plist into place
  cp -v &quot;MyApp/$environment_plist&quot; &quot;MyApp/environment.plist&quot; || failed environment

  #extract settings from the Info.plist file
  info_plist_domain=$(ls $info_plist | sed -e 's/\.plist//')
  short_version_string=$(defaults read &quot;$info_plist_domain&quot; CFBundleShortVersionString)
  bundle_identifier=$(defaults read &quot;$info_plist_domain&quot; CFBundleIdentifier)
  echo &quot;Environment set to $bundle_identifier at version $short_version_string&quot;
}

function build_app()
{
  local devired_data_path=&quot;$HOME/Library/Developer/Xcode/DerivedData&quot;

  #get the name of the workspace to be build, used as the prefix of the DerivedData directory for this build
  local workspace_name=$(echo &quot;$workspace&quot; | sed -n 's/\([^\.]\{1,\}\)\.xcworkspace/\1/p')
  #build the app
  echo &quot;Running xcodebuild &gt; xcodebuild_output ...&quot;

#  disabled overriding PRODUCT_NAME, setting applies to all built targets in Xcode 4 which renames static library target dependencies and breaks linking
#  xcodebuild -verbose -workspace &quot;$workspace&quot; -scheme &quot;$scheme&quot; -sdk iphoneos -configuration Release clean build PRODUCT_NAME=&quot;$product_name&quot; &gt;| xcodebuild_output
  xcodebuild -verbose -workspace &quot;$workspace&quot; -scheme &quot;$scheme&quot; -sdk iphoneos -configuration Release clean build &gt;| xcodebuild_output

  if [ $? -ne 0 ]
  then
    tail -n20 xcodebuild_output
    failed xcodebuild
  fi

  #locate this project's DerivedData directory
  local project_derived_data_directory=$(grep -oE &quot;$workspace_name-([a-zA-Z0-9]+)[/]&quot; xcodebuild_output | sed -n &quot;s/\($workspace_name-[a-z]\{1,\}\)\//\1/p&quot; | head -n1)
  local project_derived_data_path=&quot;$devired_data_path/$project_derived_data_directory&quot;
  #locate the .app file

#  infer app name since it cannot currently be set using the product name, see comment above
#  project_app=&quot;$product_name.app&quot;
  project_app=$(ls -1 &quot;$project_derived_data_path/Build/Products/Release-iphoneos/&quot; | grep &quot;.*\.app$&quot; | head -n1)

  # if [ $(ls -1 &quot;$project_derived_data_path/Build/Products/Release-iphoneos/$project_app&quot; | wc -l) -ne 1 ]
  if [ $(ls -1 &quot;$project_derived_data_path/Build/Products/Release-iphoneos/&quot; | grep &quot;.*\.app$&quot; | wc -l) -ne 1 ]
  then
    echo &quot;Failed to find a single .app build product.&quot;
    # echo &quot;Failed to locate $project_derived_data_path/Build/Products/Release-iphoneos/$project_app&quot;
    failed locate_built_product
  fi
  echo &quot;Built $project_app in $project_derived_data_path&quot;

  #copy app and dSYM files to the working directory
  cp -Rf &quot;$project_derived_data_path/Build/Products/Release-iphoneos/$project_app&quot; $project_dir
  cp -Rf &quot;$project_derived_data_path/Build/Products/Release-iphoneos/$project_app.dSYM&quot; $project_dir

  #rename app and dSYM so that multiple environments with the same product name are identifiable
  echo &quot;Retrieving build products...&quot;
  rm -rf $project_dir/$bundle_identifier.app
  rm -rf $project_dir/$bundle_identifier.app.dSYM
  mv -f &quot;$project_dir/$project_app&quot; &quot;$project_dir/$bundle_identifier.app&quot;
  echo &quot;$project_dir/$bundle_identifier.app&quot;
  mv -f &quot;$project_dir/$project_app.dSYM&quot; &quot;$project_dir/$bundle_identifier.app.dSYM&quot;
  echo &quot;$project_dir/$bundle_identifier.app.dSYM&quot;
  project_app=$bundle_identifier.app

  #relink CodeResources, xcodebuild does not reliably construct the appropriate symlink
  rm &quot;$project_app/CodeResources&quot;
  ln -s &quot;$project_app/_CodeSignature/CodeResources&quot; &quot;$project_app/CodeResources&quot;
}

function sign_app()
{
  echo &quot;Codesign as \&quot;$provisioning_profile\&quot;, embedding provisioning profile $mobileprovision&quot;
  #sign build for distribution and package as a .ipa
  xcrun -sdk iphoneos PackageApplication &quot;$project_dir/$project_app&quot; -o &quot;$project_dir/$project_app.ipa&quot; --sign &quot;$provisioning_profile&quot; --embed &quot;$mobileprovision&quot; || failed codesign
}

function verify_app()
{
  #verify the resulting app
  codesign -d -vvv --file-list - &quot;$project_dir/$project_app&quot; || failed verification
}

function build_ota_plist()
{
  echo &quot;Generating $project_app.plist&quot;
  cat &lt;&lt; EOF &gt; $project_app.plist
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
  &lt;key&gt;items&lt;/key&gt;
  &lt;array&gt;
    &lt;dict&gt;
      &lt;key&gt;assets&lt;/key&gt;
      &lt;array&gt;
        &lt;dict&gt;
          &lt;key&gt;kind&lt;/key&gt;
          &lt;string&gt;software-package&lt;/string&gt;
          &lt;key&gt;url&lt;/key&gt;
          &lt;string&gt;$artifacts_url/$project_app.ipa&lt;/string&gt;
        &lt;/dict&gt;
        &lt;dict&gt;
          &lt;key&gt;kind&lt;/key&gt;
          &lt;string&gt;full-size-image&lt;/string&gt;
          &lt;key&gt;needs-shine&lt;/key&gt;
          &lt;true/&gt;
          &lt;key&gt;url&lt;/key&gt;
          &lt;string&gt;$artifacts_url/$full_size_image_name&lt;/string&gt;
        &lt;/dict&gt;
        &lt;dict&gt;
          &lt;key&gt;kind&lt;/key&gt;
          &lt;string&gt;display-image&lt;/string&gt;
          &lt;key&gt;needs-shine&lt;/key&gt;
          &lt;true/&gt;
          &lt;key&gt;url&lt;/key&gt;
          &lt;string&gt;$artifacts_url/$display_image_name&lt;/string&gt;
        &lt;/dict&gt;
      &lt;/array&gt;
      &lt;key&gt;metadata&lt;/key&gt;
      &lt;dict&gt;
        &lt;key&gt;bundle-identifier&lt;/key&gt;
        &lt;string&gt;$bundle_identifier&lt;/string&gt;
        &lt;key&gt;bundle-version&lt;/key&gt;
        &lt;string&gt;$short_version_string $build_number&lt;/string&gt;
        &lt;key&gt;kind&lt;/key&gt;
        &lt;string&gt;software&lt;/string&gt;
        &lt;key&gt;subtitle&lt;/key&gt;
        &lt;string&gt;$environment_name&lt;/string&gt;
        &lt;key&gt;title&lt;/key&gt;
        &lt;string&gt;$project_app&lt;/string&gt;
      &lt;/dict&gt;
    &lt;/dict&gt;
  &lt;/array&gt;
&lt;/dict&gt;
&lt;/plist&gt;
EOF
}

echo &quot;**** Validate Keychain&quot;
validate_keychain
echo
echo &quot;**** Describe SDKs&quot;
describe_sdks
echo
echo &quot;**** Describe Workspace&quot;
describe_workspace
echo
echo &quot;**** Set Environment&quot;
set_environment
echo
echo &quot;**** Increment Bundle Version&quot;
increment_version
echo
echo &quot;**** Build&quot;
build_app
echo
echo &quot;**** Package Application&quot;
sign_app
echo
echo &quot;**** Verify&quot;
verify_app
echo
echo &quot;**** Prepare OTA Distribution&quot;
build_ota_plist
echo
echo &quot;**** Complete!&quot;
</pre>
<p>That is quite a few functions but the bottom of the script steps through them in what is hopefully an understandable sequence.</p>
<ol>
<li>Unlock the keychain containing the private key and provisioning profile used to sign the ad hoc build. Necessary since the TeamCity user&#8217;s login keychain may be locked when this build runs.</li>
<li>List the available sdks on the build machine (unnecessary but I found it helpful when debugging build settings).</li>
<li>List the schemes found in the workspace to be built (again purely for debugging).</li>
<li>Copy a plist containing application settings to &#8220;environment.plist&#8221; which will be copied into the app bundle when built and used to define application behavior, for example it contains the url of the server this build should communicate with.</li>
<li>Build the app using the specified workspace and scheme. Copy the resulting app and dSYM to the project directory so TeamCity can easily find them as build artifacts.</li>
<li>Sign the app using the specified mobile provisioning profile and create a &#8220;.ipa&#8221; package.</li>
<li>Verify that the app was successfully signed.</li>
<li>Create a plist to allow over the air installation of the app.</li>
</ol>
<p>Once run any device which has been added to the mobile provisioning profile used to sign this build can install the app just by visiting (using an appropriate %system.teamcity.buildType.id% for the TeamCity build configuration).</p>
<blockquote><p>
itms-services://?action=download-manifest&amp;url=http://teamcity.example.com:8111/guestAuth/repository/download/%system.teamcity.buildType.id%/.lastSuccessful/project_name.acceptance.app.plist
</p></blockquote>
<p>Possible issues:</p>
<ul>
<li>Access to the keychain will present a security dialog the first time this build runs so it was necessary for me to sign into the TeamCity user&#8217;s account using VNC and allow access to that keychain.</li>
<li>I found that builds occasionally failed to correctly create the CodeResources symlink so I recreate it manually. When this link was broken the ipa would fail verification.</li>
<li>An iOS device won&#8217;t be able to install the app if the artifacts require authenticating to the TeamCity server so I enabled guest access. Alternately I could have exposed those artifacts through some other service and created a nice installation guide page which links to them if I didn&#8217;t want to allow guest access to my TeamCity server.</li>
</ul>
<p>For additional resources for building over the air distribution builds take a look at:</p>
<p>Mike Nachbaur&#8217;s posts on &#8220;<a href="http://nachbaur.com/blog/how-to-automate-your-iphone-app-builds-with-hudson">How to Automate your iPhone App Builds with Hudson</a>&#8221; and &#8220;<a href="http://nachbaur.com/blog/building-ios-apps-for-over-the-air-adhoc-distribution">Building iOS Apps for Over the Air Ad Hoc Distribution</a>&#8220;.<br />
Vincent Daubry&#8217;s &#8220;<a href="http://blog.octo.com/en/automating-over-the-air-deployment-for-iphone/">Automating Over The Air Deployment for iPhone</a>&#8220;.<br />
Basil Shkara&#8217;s &#8220;<a href="http://www.neat.io/posts/2010/10/27/automated-ota-ios-app-distribution.html">Automated OTA iOS App Distribution</a>&#8220;.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/05/04/automated-ad-hoc-builds-using-xcode-4/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Building Xcode 4 projects from the command line</title>
		<link>http://blog.carbonfive.com/2011/04/06/building-xcode-4-projects-from-the-command-line/</link>
		<comments>http://blog.carbonfive.com/2011/04/06/building-xcode-4-projects-from-the-command-line/#comments</comments>
		<pubDate>Wed, 06 Apr 2011 10:00:59 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=3336</guid>
		<description><![CDATA[The Xcode 4 developer tools introduced some changes to the xcodebuild command line tool. Instead of specifying a project and target developers can now provide a workspace and scheme to build. &#62; /Developer_Xcode4/usr/bin/xcodebuild -help Usage: xcodebuild [-project ] [[-target ]&#8230;&#124;-alltargets] &#8230; <a href="http://blog.carbonfive.com/2011/04/06/building-xcode-4-projects-from-the-command-line/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Xcode 4 developer tools introduced some changes to the xcodebuild command line tool. Instead of specifying a project and target developers can now provide a workspace and scheme to build.<br />
<span id="more-3336"></span></p>
<blockquote><p>&gt; /Developer_Xcode4/usr/bin/xcodebuild -help<br />
Usage: xcodebuild [-project ] [[-target ]&#8230;|-alltargets] [-configuration ] [-arch ]&#8230; [-sdk [|]] [=]&#8230; []&#8230;<br />
       xcodebuild -workspace  -scheme  [-configuration ] [-arch ]&#8230; [-sdk [|]] [=]&#8230; []&#8230;<br />
       xcodebuild -version [-sdk [|] [] ]<br />
       xcodebuild -list [[-project ]|[-workspace ]]<br />
       xcodebuild -showsdks
</p></blockquote>
<p>The workspace and scheme names should be known from the project. The default configuration options are &#8220;Debug&#8221; and &#8220;Release&#8221;. The &#8220;-showsdks&#8221; option lists available SDKs.</p>
<blockquote><p>&gt; /Developer_Xcode4/usr/bin/xcodebuild -showsdks<br />
Mac OS X SDKs:<br />
	Mac OS X 10.6                 	-sdk macosx10.6</p>
<p>iOS SDKs:<br />
	iOS 4.3                       	-sdk iphoneos4.3</p>
<p>iOS Simulator SDKs:<br />
	Simulator &#8211; iOS 3.2           	-sdk iphonesimulator3.2<br />
	Simulator &#8211; iOS 4.0           	-sdk iphonesimulator4.0<br />
	Simulator &#8211; iOS 4.1           	-sdk iphonesimulator4.1<br />
	Simulator &#8211; iOS 4.2           	-sdk iphonesimulator4.2<br />
	Simulator &#8211; iOS 4.3           	-sdk iphonesimulator4.3
</p></blockquote>
<p>Available build actions are listed in the xcodebuild man pages. Unfortunately these do not match the actions available in a scheme and the command line does not provide a mechanism for testing, running, profiling, or analyzing builds.</p>
<blockquote><p>&gt; man xcodebuild<br />
&#8230;</p>
<p>buildaction &#8230;<br />
           Specify a build action (or actions) to perform on the target. Available build actions are:</p>
<p>           build       Build the target in the build root (SYMROOT).  This is the default build action.</p>
<p>           archive     Archive a scheme from the build root (SYMROOT).  This requires specifying a workspace and scheme.</p>
<p>           installsrc  Copy the source of the project to the source root (SRCROOT).</p>
<p>           install     Build the target and install it into the target&#8217;s installation directory in the distribution root (DSTROOT).</p>
<p>           clean       Remove build products and intermediate files from the build root (SYMROOT).
</p></blockquote>
<p>Given all of these configuration options it is then possible to perform builds from the command line.</p>
<blockquote><p>&gt; /Developer_Xcode4/usr/bin/xcodebuild -workspace WrappingScrollView.xcworkspace -scheme WrappingScrollViewDemo -sdk iphonesimulator4.3 -configuration Debug clean build<br />
Build settings from command line:<br />
    SDKROOT = iphonesimulator4.3</p>
<p>=== CLEAN NATIVE TARGET JCFWrappingScrollView OF PROJECT JCFWrappingScrollView WITH CONFIGURATION Debug ===<br />
Check dependencies</p>
<p>&#8230;</p>
<p>** CLEAN SUCCEEDED **</p>
<p>=== BUILD NATIVE TARGET JCFWrappingScrollView OF PROJECT JCFWrappingScrollView WITH CONFIGURATION Debug ===<br />
Check dependencies</p>
<p>ProcessPCH /Users/Jonah/Library/Developer/Xcode/DerivedData/WrappingScrollView-fqscqfdtpoqunuanehtbgpseirdj/Build/PrecompiledHeaders/JCFWrappingScrollView-Prefix-dkkjrdaonxokgpbkgjfmpmcpadoz/JCFWrappingScrollView-Prefix.pch.gch JCFWrappingScrollView/JCFWrappingScrollView-Prefix.pch normal i386 objective-c com.apple.compilers.llvmgcc42<br />
    cd /Users/Jonah/Desktop/WrappingScrollView/JCFWrappingScrollView<br />
    setenv LANG en_US.US-ASCII</p>
<p>&#8230;</p>
<p>** BUILD SUCCEEDED **
</p></blockquote>
<p>Hopefully that is sufficient to automatically produce ad-hoc builds on a continuous integration server.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/04/06/building-xcode-4-projects-from-the-command-line/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Using Open Source Static Libraries in Xcode 4</title>
		<link>http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/</link>
		<comments>http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/#comments</comments>
		<pubDate>Mon, 04 Apr 2011 18:00:21 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=3196</guid>
		<description><![CDATA[Xcode 4.0.1 allows us to more easily create and use third party libraries in iOS projects. I think the process is still more complicated than it needs to be. Xcode&#8217;s documentation suggests that it should automatically detect implicit dependencies and &#8230; <a href="http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Xcode 4.0.1 allows us to more easily create and use third party libraries in iOS projects. I think the process is still more complicated than it needs to be. Xcode&#8217;s documentation suggests that it should automatically detect implicit dependencies and index classes across workspaces but I have not found this to be the case. Here I&#8217;ll cover the steps I have found for creating and sharing code between projects and with other developers.<br />
<span id="more-3196"></span></p>
<ol>
<li><a href="#background">Background</a></li>
<li><a href="#using_a_static_library">Using a Static Library</a></li>
<li><a href="#creating_a_static_library">Creating a Static Library</a></li>
<li><a href="#future_improvements">Future Improvements</a></li>
</ol>
<p><a name="background"></a></p>
<h2>Background</h2>
<h3>Workspaces:</h3>
<p>Xcode 4 introduced the concept of <a href="http://developer.apple.com/library/ios/#featuredarticles/XcodeConcepts/Concept-Workspace.html">workspaces</a> as containers for multiple projects. There are a couple of key behaviors of workspaces which we want to build on when choosing how to share code across projects.</p>
<ul>
<li>By default, all the Xcode projects in a workspace are built in the same directory, referred to as the workspace build directory.</li>
<li>Xcode examines the files in the build directory to discover implicit dependencies.</li>
<li>Each project in a workspace continues to have its own independent identity.</li>
</ul>
<h3>Schemes:</h3>
<p>Within a workspace or within a project which is a member of a workspace we have <a href="http://developer.apple.com/library/ios/#featuredarticles/XcodeConcepts/Concept-Schemes.html">schemes</a>. Schemes replace the Active Target, Build Configuration, and Executable settings from Xcode 3 and define which targets to build, the order in which to build them, and what action to take when a build is complete. We&#8217;ll want our shared code to easily fit into the scheme of any projects which use it. The <a href="http://developer.apple.com/library/mac/#documentation/IDEs/Conceptual/Xcode4TransitionGuide/Orientation/Orientation.html#//apple_ref/doc/uid/TP40009984-CH5-SW26">Xcode 4 Transition Guide</a> covers this new structure in more detail.</p>
<h3>Targets:</h3>
<p>Within a scheme we have one or more build <a href="http://developer.apple.com/library/ios/#featuredarticles/XcodeConcepts/Concept-Targets.html">targets</a> which define a set of source files to build, the settings used to build those files, and any dependencies on the build products of other targets which must be completed first. Ultimately we would like a consumer of our code to be able to state that their project&#8217;s build target depends on our shared code and have Xcode build this shared code and make it available to the active build target. We can achieve that by providing a project containing the code to be shared and a static library build target which packages it into a build product other developers can add as a build target dependency.<br />
<a name="using_a_static_library"></a></p>
<h2>Using a static library</h2>
<ol>
<li><a href="#creating_a_workspace">Creating a workspace</a></li>
<li><a href="#adding_projects_to_a_workspace">Adding projects to a workspace</a></li>
<li><a href="#adding_build_target_dependencies">Adding build target dependencies</a></li>
<li><a href="#adding_the_static_librarys_headers">Adding the static library&#8217;s headers</a></li>
<li><a href="#configuring_the_projects_scheme">Configuring the project&#8217;s scheme</a></li>
<li><a href="#fixing_indexing">Fixing indexing</a></li>
</ol>
<p><a name="creating_a_workspace"></a></p>
<h3>Creating a workspace</h3>
<p>We can create a new empty workspace from Xcode&#8217;s file menu or open an existing project and select &#8220;Save As Workspace&#8230;&#8221; to create a new workspace containing our project. This will create a &#8220;.xcworkspace&#8221; package in the file system.</p>
<p><div id="attachment_3314" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/empty_workspace.png"><img class="size-medium wp-image-3314" title="empty workspace" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/empty_workspace.png?w=300" alt="An empty Xcode 4 workspace" width="300" height="147" /></a><p class="wp-caption-text">An empty Xcode 4 workspace</p></div><br />
<a name="adding_projects_to_a_workspace"></a></p>
<h3>Adding projects to a workspace</h3>
<p>Once we have a workspace we can right-click in the workspace&#8217;s navigator to create a new project or add an existing &#8220;.xcodeproj&#8221; package.</p>
<p><div id="attachment_3317" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/adding_a_project.png"><img class="size-medium wp-image-3317" title="adding a project" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/adding_a_project.png?w=300" alt="Adding a new project to a workspace" width="300" height="184" /></a><p class="wp-caption-text">Adding a new project to a workspace</p></div></p>
<p><div id="attachment_3318" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/adding_an_existing_project.png"><img class="size-medium wp-image-3318" title="adding an existing project" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/adding_an_existing_project.png?w=300" alt="Adding an existing project to a workspace" width="300" height="274" /></a><p class="wp-caption-text">Adding an existing project to a workspace</p></div></p>
<p>We want to end up with a single workspace containing our app&#8217;s project and the projects for any static libraries we are going to depend on. It is worth noting that these projects are all siblings in the workspace, our static libraries are not added as references within our app&#8217;s project.</p>
<p>&nbsp;<br />
<a name="adding_build_target_dependencies"></a></p>
<h3>Adding build target dependencies</h3>
<p>With all of the projects we need available in our workspace we can select our app&#8217;s build target and add a static library to the &#8220;Link Binary With Libraries&#8221; build phase.</p>
<p><div id="attachment_3319" class="wp-caption alignnone" style="width: 224px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/linkable_libraries.png"><img class="size-medium wp-image-3319" title="linkable libraries" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/linkable_libraries.png?w=214" alt="Libraries and frameworks available to add to the &quot;Link Binary With Libraries&quot; build phase" width="214" height="300" /></a><p class="wp-caption-text">Libraries and frameworks available to add to the &quot;Link Binary With Libraries&quot; build phase</p></div></p>
<p><div id="attachment_3320" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/linking_with_static_library.png"><img class="size-medium wp-image-3320" title="linking with a static library" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/linking_with_static_library.png?w=300" alt="A static library added to the &quot;Link Binary With Libraries&quot; build phase" width="300" height="170" /></a><p class="wp-caption-text">A static library added to the &quot;Link Binary With Libraries&quot; build phase</p></div><br />
<a name="adding_the_static_librarys_headers"></a></p>
<h3>Adding the static library&#8217;s headers</h3>
<p>We also need to make sure that our app&#8217;s build target can locate the public headers used in this static library. Open the &#8220;Build Settings&#8221; tab and locate the &#8220;User Header Search Paths&#8221; setting. Set this to &#8220;$(BUILT_PRODUCTS_DIR)&#8221; (or &#8220;$(BUILT_PRODUCTS_DIR)/static_library_name&#8221; if we want to be more specific but then we&#8217;ll have to update this setting every time we add another library) and check the &#8220;Recursive&#8221; check box. Now our built target will search our workspace&#8217;s shared build directory to locate linkable header files.</p>
<p><div id="attachment_3321" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/header_search_path_value.png"><img class="size-medium wp-image-3321" title="user header search paths value" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/header_search_path_value.png?w=300" alt="Setting the User Header Search Paths" width="300" height="194" /></a><p class="wp-caption-text">Setting the User Header Search Paths</p></div></p>
<p><div id="attachment_3322" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/set_user_header_search_paths.png"><img class="size-medium wp-image-3322" title="user header search paths set" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/set_user_header_search_paths.png?w=300" alt="User Header Search Paths set" width="300" height="147" /></a><p class="wp-caption-text">User Header Search Paths set</p></div></p>
<p>The &#8220;User Header Search Paths&#8221; setting defines the headers available as quoted imports (eg &#8220;#import &#8220;MyLibraryClass.h&#8221;) while the &#8220;Header Search Paths&#8221; setting defines those headers available as bracketed imports (eg &#8220;#import ). I&#8217;ve found that Xcode will only autocomplete header names in the quoted form so I always add libraries to the user header search path even though, from my project&#8217;s perspective, they might be more appropriate as system level (angle bracketed) libraries.</p>
<p>When using a static library which includes categories we will also have to add the &#8220;-ObjC&#8221; flag to the &#8220;Other Linker Flags&#8221; build setting. This will force the linker to load all objective-c classes and categories from the library. If the library contains only categories &#8220;-all_load&#8221; or &#8220;-force_load&#8221; may be needed as well. See <a href="http://developer.apple.com/library/mac/#qa/qa1490/_index.html">Technical Q&amp;A QA1490</a> for a more detailed explanation of these settings.<br />
<a name="configuring_the_projects_scheme"></a></p>
<h3>Configuring the project&#8217;s scheme</h3>
<p>At this point Xcode should have detected this implicit dependency between our app&#8217;s project and the static library&#8217;s project and have automatically configured our schemes correctly. Unfortunately I haven&#8217;t found this to be the case in practice. Instead we will have to edit our current scheme and add the static library&#8217;s build target before our app&#8217;s build target.</p>
<p><div id="attachment_3323" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/setting_target_build_order.png"><img class="size-medium wp-image-3323" title="setting target build order" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/setting_target_build_order.png?w=300" alt="Setting the scheme's target build order" width="300" height="205" /></a><p class="wp-caption-text">Setting the scheme&#039;s target build order</p></div><br />
<a name="fixing_indexing"></a></p>
<h3>Fixing indexing</h3>
<p>At this point we should be able to include headers from dependent static libraries, use the included classes, and still successfully build our app. Unfortunately Xcode will not show any classes from these linked static libraries in code completion despite the workspace documentation stating that &#8220;indexing is done across the entire workspace, extending the scope of content-aware features such as code completion and refactoring.&#8221;<br />
As a workaround we can drag the public headers from the static library&#8217;s project into our app&#8217;s project, adding them as references. These headers do not need to be included in any of our build targets, simply having references to the headers in our project will allow their classes to appear in code completion.<br />
<a name="creating_a_static_library"></a></p>
<h2>Creating a Static Library</h2>
<p>If we plan on releasing some of our own code for reuse as a static library there are several things we should do to make sure that the process described above is as easy and simple as possible for our library&#8217;s users.</p>
<ol>
<li><a href="#namespace_classes_appropriately">Namespace classes appropriately</a></li>
<li><a href="#create_a_build_target">Create a build target</a></li>
<li><a href="#expose_public_headers">Expose public headers</a></li>
<li><a href="#set_the_installation_directory">Set the installation directory</a></li>
<li><a href="#set_the_public_header_path">Set the public header path</a></li>
<li><a href="#exclude_user_specific_files_from_vcs">Exclude user specific files from VCS</a></li>
</ol>
<p><a name="namespace_classes_appropriately"></a></p>
<h3>Namespace classes appropriately</h3>
<p>Use an appropriate <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html#//apple_ref/doc/uid/20001281-1002226">prefix</a> for classes, protocols, functions, and constants in the library to prevent collisions with names in the library&#8217;s user&#8217;s project.<br />
<a name="create_a_build_target"></a></p>
<h3>Create a build target</h3>
<p>Provide a static library build target in the project for our users to link against. Xcode provides templates for creating projects with static libraries or adding static library build targets to existing projects.<br />
<a name="expose_public_headers"></a></p>
<h3>Expose public headers</h3>
<p>Determine which header files should be visible to users of the library. Provide a clearly named group containing these headers so that our library&#8217;s users can easily locate them as part of the workaround described in &#8220;Fixing Indexing&#8221; above. This also helps us clarify what the public interface our library provides is and what classes are implementation details which are likely to change as the library evolves.</p>
<p>For each public header file make sure it is set as &#8220;public&#8221; in the &#8220;Target Membership&#8221; section of the inspector pane. Only public headers are going to be available for our users to import.</p>
<p><div id="attachment_3326" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/making_headers_public.png"><img class="size-medium wp-image-3326" title="making headers public" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/making_headers_public.png?w=300" alt="Making a header file public" width="300" height="147" /></a><p class="wp-caption-text">Making a header file public</p></div><br />
<a name="set_the_installation_directory"></a></p>
<h3>Set installation directory</h3>
<p>Our static library build target is going to be a member of a user&#8217;s workspace and subject to that workspace&#8217;s installation rules. Our static library build product could therefore be installed in a location set by Xcode&#8217;s preferences, in the derived data path, or in a path specified by our build target. Since we can&#8217;t control the user&#8217;s settings we should make sure our library is well behaved in all cases. I set the &#8220;Installation Directory&#8221; build setting to &#8220;$(BUILT_PRODUCTS_DIR)&#8221; so that the static library build product can be found in a known location and set the &#8220;Skip Install&#8221; build setting to &#8220;Yes&#8221; to avoid accidentally installing iOS libraries into &#8220;/usr/local/lib&#8221;.</p>
<p><div id="attachment_3327" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/set_installation_directory.png"><img class="size-medium wp-image-3327" title="set installation directory" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/set_installation_directory.png?w=300" alt="Setting the installation directory" width="300" height="164" /></a><p class="wp-caption-text">Setting the installation directory</p></div><br />
<a name="set_the_public_header_path"></a></p>
<h3>Set the public header path</h3>
<p>We need to specify a location to copy our static library&#8217;s public headers to so that they can be included in our users&#8217; header search paths. Setting the &#8220;Public Headers Folder Path&#8221; to &#8220;$(TARGET_NAME)&#8221; will create a folder named after our static library build target in the workspace&#8217;s shared build directory and be indexed by the &#8220;User Header Search Paths&#8221; setting described above.</p>
<p><div id="attachment_3328" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.carbonfive.com/wp-content/uploads/2011/04/set_public_headers_path.png"><img class="size-medium wp-image-3328" title="set public headers path" src="http://blog.carbonfive.com/wp-content/uploads/2011/04/set_public_headers_path.png?w=300" alt="Setting the public headers path for the static library" width="300" height="147" /></a><p class="wp-caption-text">Setting the public headers path for the static library</p></div><br />
<a name="exclude_user_specific_files_from_vcs"></a></p>
<h3>Exclude user specific files from VCS</h3>
<p>Our workspace and project include a number of files which contain data relevant only to our user account; window positions, open files, and so on. There&#8217;s no need to check these into source control, at least not in our release branch, so let&#8217;s set some reasonable ignore rules in git or whatever VCS we are using. Github provides a convenient set of <a href="https://github.com/github/gitignore">.gitignore files</a><br />
<a name="future_improvements"></a></p>
<h2>Future Improvements</h2>
<p>Hopefully Xcode 4 will eventually live up to the promise of it&#8217;s documentation and consistently auto-detect implicit dependencies and index files across the workspace correctly. There certainly seem to be a number of other developers struggling with this behavior:[<a href="https://devforums.apple.com/message/390470#390470">1</a>], [<a href="https://devforums.apple.com/message/399673#399673">2</a>], [<a href="https://devforums.apple.com/message/397932#397932">3</a>], [<a href="https://devforums.apple.com/message/399316#399316">4</a>], [<a href="https://devforums.apple.com/message/375741#375741">5</a>], [<a href="https://devforums.apple.com/message/377781#377781">6</a>], [<a href="http://stackoverflow.com/questions/5427396/whats-the-correct-way-to-configure-xcode-4-workspaces-to-build-dependencies-when">7</a>], [<a href="http://stackoverflow.com/questions/5483909/how-should-i-manage-dependencies-across-projects-in-an-xcode-workspace">8</a>]. Until that indexing improves I find that this process is at least somewhat simpler and cleaner than trying to maintain simulator and device compatible static library builds in Xcode 3.<br />
I&#8217;ve found this pattern preferable to copying third party classes directly into my projects as it allows me to easily keep version history and make updates to static library projects in my workspace and avoids coupling my project too closely to the private structure and contents of the static library.<br />
Please let me know if you can see any areas where this pattern could be improved or if you&#8217;ve found your own alternative means of sharing code.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/feed/</wfw:commentRss>
		<slash:comments>64</slash:comments>
		</item>
		<item>
		<title>Abusing UIViewControllers</title>
		<link>http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/</link>
		<comments>http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 12:00:16 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1699</guid>
		<description><![CDATA[UIViewControllers are a fundamental building block of most iOS applications. Unfortunately many developers seem to use them in unintended and unsupported ways which leaves their apps vulnerable to bugs, rejections, unpredictable behavior under new iOS releases, and with controllers which &#8230; <a href="http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html">UIViewController</a>s are a fundamental building block of most iOS applications. Unfortunately many developers seem to use them in unintended and unsupported ways which leaves their apps vulnerable to bugs, rejections, unpredictable behavior under new iOS releases, and with controllers which are difficult to update or reuse. The core misconceptions behind this abuse of UIViewController are understandable. Apple presents UIViewControllers as a key element of an app&#8217;s navigation and interface stating &#8220;custom view controllers are the primary coordinating objects for your application’s content&#8221;. The basic application templates are defined in terms of their UIViewController behavior; &#8220;navigation-based&#8221;, &#8220;tab bar&#8221;, &#8220;split-view based&#8221;. From our first exposure to the platform developers are presented with UIViewControllers as classes for managing views and the transitions between them. Sadly those examples present a pattern which we, as iOS developers outside Apple, cannot follow or build on.</p>
<p>Any app which contains code like<br />
<code>[viewController.view addSubview:someOtherViewController.view];</code><br />
or<br />
<code>viewController.view.bounds = CGRectMake(50, 50, 100, 200);</code><br />
or which loads a nib doing the equivalent is abusing UIViewControllers. Given time this will emerge as bugs or at least pain for developers continuing to work on the app.</p>
<p><strong>What? How is that wrong?</strong><br />
<span id="more-1699"></span><br />
The core problem, and surprise for too many developers, is stated in the &#8220;View Controller Programing Guide for iOS&#8221; in &#8220;<a href="http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html#//apple_ref/doc/uid/TP40007457-CH112-SW12">About Custom View Controllers</a>&#8220;:</p>
<blockquote><p>Each custom view controller object you create is responsible for managing all of the views in a single view hierarchy. In iPhone applications, the views in a view hierarchy traditionally cover the entire screen, but in iPad applications they may cover only a portion of the screen. The one-to-one correspondence between a view controller and the views in its view hierarchy is the key design consideration. You should not use multiple custom view controllers to manage different portions of the same view hierarchy. Similarly, you should not use a single custom view controller object to manage multiple screens worth of content.
</p></blockquote>
<p>Essentially the <em><a href="http://developer.apple.com/library/ios/documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/doc/uid/TP40006817-CH3-SW33">rootViewController</a></em> of the current UIWindow should be the only UIViewController with a visible view.</p>
<p>With multiple UIViewController&#8217;s views visible at once some of those controllers may not receive important messages like <em>-viewWillAppear:</em> or <em>-didReceiveMemoryWarning</em>. Additionally some of their properties like <em>parentViewController</em> and <em>interfaceOrientation</em> may not be set or updated as expected.</p>
<p>&#8220;<a href="http://developer.apple.com/library/ios/#qa/qa1688/_index.html">Why won&#8217;t my UIViewController rotate with the device?</a>&#8221; states this even more explicitly.</p>
<blockquote><p> If you add an additional view controller&#8217;s UIView property to UIWindow (at the same level as your primary view controller) via the following:</p>
<p>[myWindow addSubview:anotherController.view];</p>
<p>this additional view controller will not receive rotation events and will never rotate. Only the first view controller added to UIWindow will rotate. </p></blockquote>
<p>Now Apple is able to provide &#8220;container view controllers&#8221; like UINavigationController and UITabBarController which manage the presentation of other UIViewController&#8217;s views. Unfortunately to do so requires the use of private API calls which are not available for any app seeking approval for distribution in the App Store (discussed in more detail here: <a href="https://devforums.apple.com/message/310806#310806">https://devforums.apple.com/message/310806#310806</a>). We can come close but without a supported path for implementing custom container view controllers nesting UIViewControllers&#8217; views will not give us all the behavior we expect from a UIViewController.</p>
<p><strong>Isn&#8217;t close good enough?</strong></p>
<p>Not really. We can implement a custom container view controller which sends messages like <em>-viewWillAppear</em> to its child view controllers but that only solves part of the problem. </p>
<ul>
<li>Without being able to rely on <em>interfaceOrientation</em> those child view controllers may never support rotation correctly.<br />
Since view controllers&#8217; views are expected to fill the window views &#8220;behind&#8221; modal view controllers may not be drawn or may be unloaded while visible.</li>
<li>Without properties like <em>parentViewController</em> or <em>navigationController</em> being set all of our child view controllers need to be aware of how they are being presented and the fact that they cannot rely on all the behavior they should be able to expect from inheriting from UIViewController.</li>
<li>Child view controllers may not be properly inserted into the responder chain so they may never see events passed up the chain from their views.</li>
</ul>
<p>With no public setters available for these properties or documentation of these behaviors there&#8217;s currently no way to resolve this situation (see this thread for further discussion: <a href="https://devforums.apple.com/message/365171#365171">https://devforums.apple.com/message/365171#365171</a>). Since there is currently no supported means of creating container view controllers those behaviors which do work now are not guaranteed to continue to function in future iOS updates and may vary between existing iOS versions.<br />
By nesting UIViewControllers we create a UIViewController instance which cannot rely on the entire contract offered by UIViewController. A non-obvious and context specific problem for any developer working on the app in the future.</p>
<p><strong>So what&#8217;s the alternative?</strong></p>
<p>The &#8220;<a href="http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html#//apple_ref/doc/uid/TP40007457-CH112-SW12">View Controller Programming Guide for iOS</a>&#8221; at least suggests an alternative:</p>
<blockquote><p>Note: If you want to divide a view hierarchy into multiple subareas and manage each one separately, use generic controller objects (custom objects descending from NSObject) instead of view controller objects to manage each subarea. Then use a single view controller object to manage the generic controller objects.
</p></blockquote>
<p>A controller does not necessarily have to be a subclass of UIViewController. We can create controller objects responsible for managing specific behaviors or portions of our view and have these controllers inherit from NSObject instead of from UIViewController. This allows you to break up your app&#8217;s controller logic into manageable classes with clear responsibilities while still following the limitations of UIViewController. This works well when you want to have different controllers manage different sections of a single view hierarchy. </p>
<p><code><br />
@interface SampleController : NSObject  {<br />
}<br />
@end<br />
</code></p>
<p>This is however an inadequate replacement for custom container view controllers which should be able to manage transitions between arbitrary UIViewControllers. Instead we have to either reinvent much of UIViewController&#8217;s behavior (<em>-viewWillAppear:</em> and <em>-viewDidDisappear:</em> style lifecycle methods, unloading and reloading of views on demand, transformation of views in response to device rotations) or abuse UIViewController and risk producing unstable apps.</p>
<p><code><br />
@protocol ViewController<br />
    - (void)viewDidAppear:(BOOL)animated;<br />
    - (void)viewDidDisappear:(BOOL)animated;<br />
    - (void)viewWillAppear:(BOOL)animated;<br />
    - (void)viewWillDisappear:(BOOL)animated;<br />
    -(UIView *)view;<br />
@end</p>
<p>@interface SampleController : NSObject  {<br />
}<br />
@end</p>
<p>@interface SampleContainerViewController : UIViewController {<br />
}<br />
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated;<br />
@property(nonatomic, copy) NSArray *viewControllers;<br />
@end<br />
</code></p>
<p>For now I have found that the best solution is to stay within the supported constraints of UIViewController and build custom non-UIViewController controllers as necessary. Have you found a better alternative, chosen to use UIViewControllers anyway, or avoided this problem entirely?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/feed/</wfw:commentRss>
		<slash:comments>59</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #7: transport cost is zero</title>
		<link>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/</link>
		<comments>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 19:00:18 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1702</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite">Bandwidth is infinite.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-4-the-network-is-secure">The network is secure.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-5-topology-doesnt-change">Topology doesn&#8217;t change.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-6-there-is-one-administrator">There is one administrator.</a></li>
<li><strong>Transport cost is zero.</strong></li>
<li><a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">The network is homogeneous.</a></li>
</ol>
<p><span id="more-1702"></span><br />
Fallacy #7: &#8220;transport cost is zero&#8221;.</p>
<p>Arnon Rotem-Gal-Oz&#8217;s <a href="http://www.rgoarchitects.com/Files/fallacies.pdf">explanation</a> of this fallacy points out two possible interpretations, both of which can be problematic mistakes.</p>
<p>First you can consider the cost of moving data between your application and the network interface. The performance impact of serializing objects or parsing data add a cost above and beyond the limitations of bandwidth and latency. Apple&#8217;s <a href="http://developer.apple.com/videos/wwdc/2010/">2010 WWDC session 117</a> &#8220;building a server-driven user experience&#8221; for their comparison of the size and load time of data in xml, json, and plists (slide #40 &amp; 41 at ~27:30). While the size of each format was similar the time required to parse the result varied tremendously; 812ms for xml, 416ms for json, 140ms for an ascii plist and only 19ms for a binary plist.</p>
<p>Secondly you can consider the cost of maintaining network services and infrastructure. How much load does each user place on your servers and what do they cost to run? How many concurrent requests can your servers actually handle and what does it cost to scale those systems? What does using your app cost your users who live with monthly data limits or pay on a per-kilobyte basis?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone Distributed Computing Fallacy #5: topology doesn&#8217;t change</title>
		<link>http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/</link>
		<comments>http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 22:00:09 +0000</pubDate>
		<dc:creator>Jonah Williams</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://blog.carbonfive.com/?p=1691</guid>
		<description><![CDATA[Reviewing the 8 classic &#8220;fallacies of distributed computing&#8221; and how we can avoid them when writing iOS applications. The fallacies of distributed computing The network is reliable. Latency is zero. Bandwidth is infinite. The network is secure. Topology doesn&#8217;t change. &#8230; <a href="http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Reviewing the 8 classic &#8220;<a href="http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing">fallacies of distributed computing</a>&#8221; and how we can avoid them when writing iOS applications.</p>
<p><em>The fallacies of distributed computing</em></p>
<ol>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-1-the-network-is-reliabl">The network is reliable.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/fallacy-2-latency-is-zero">Latency is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-3-bandwidth-is-infinite">Bandwidth is infinite.</a></li>
<li><a href="http://blog.carbonfive.com/2010/11/iphone/iphone-distributed-computing-fallacy-4-the-network-is-secure">The network is secure.</a></li>
<li><strong>Topology doesn&#8217;t change.</strong></li>
<li><a href="http://blog.carbonfive.com/2010/12/iphone/iphone-distributed-computing-fallacy-6-there-is-one-administrator">There is one administrator.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/03/iphone-distributed-computing-fallacy-7-transport-cost-is-zero/">Transport cost is zero.</a></li>
<li><a href="http://blog.carbonfive.com/2010/12/06/iphone-distributed-computing-fallacy-8-the-network-is-homogeneous/">The network is homogeneous.</a></li>
</ol>
<p><span id="more-1691"></span><br />
Fallacy #5: &#8220;topology doesn&#8217;t change&#8221;.</p>
<p>WWAN connections use significantly more power than WiFi connections. This becomes important when working with long lived connections or streaming media. A connection established over the WWAN will keep that interface active even if a WiFi network becomes available. To avoid running both interfaces it is up to the app to close and re-establish any active connections on the newly available network interface. Use Apple&#8217;s Reachability example to monitor changes in available interfaces and react as necessary. Also take a look at Paul Danbold&#8217;s &#8220;<a href="http://developer.apple.com/videos/iphone/#video-advanced-networking">Advanced networking</a>&#8221; talk from the 2009 Tech Talk World Tour.</p>
<p>Those changes to the network are also likely to result in changes to the device&#8217;s available bandwidth and latency so apps which make decisions based on those characteristics may need to monitor their connections and adapt to changing conditions. Since apps which stream significant amounts of audio or video are required to use <a href="http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008332-CH1-DontLinkElementID_30">http live streaming</a> they can automatically switch between available streams designed for higher or lower bandwidth connections as network conditions change.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.carbonfive.com/2010/12/02/iphone-distributed-computing-fallacy-5-topology-doesnt-change/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

