Picking your Swift toolchain from xcodebuild

With Xcode 8 xcodebuild uses Swift 3 to build by default. This will be great in about six months, but right now it’s somewhat of a pain. I am using Carthage as my dependency manager and all of those are using Swift 2.x still.

If you want to build your Carthage dependencies (or anything from the command line for that matter) using Swift 2.3, add the TOOLCHAINS parameter.

TOOLCHAINS=com.apple.dt.toolchain.Swift_2_3 carthage build  

Update: As of Carthage 0.17 you can use a --toolchain option. This doesn’t help with raw xcodebuild obviously.

Read more about. . .

Auto Layout Debugging In Swift

I’ve been working with Swift primarily over the last month. Recently I started working on a new custom interface piece that was having some rendering issues with its layout constraints. I went into LLDB and quickly realized that using private methods such as _autolayoutTrace and recursiveDescription to print out a hierarchy of my views and see ambiguity wasn’t possible out of the box.

The reason for this is that when you’re in a Swift frame, LLDB is expecting you to call a Swift method it knows about. Since _autolayoutTrace and the like are private API, they don’t have any visibility to Swift. Safety!

There are a few different ways to get around this. The first is straight in LLDB. You can use the expr command to tell LLDB that you are passing it a snippet of Objective-C code like so:

<code class="bash">expr -l objc++ -o -- [[UIWindow keyWindow] _autolayoutTrace]  

What we’re doing here is printing out our entire view hierarchy to the debugger. Frequently typing that long of a statement is obviously a bit tedious, so I tend to put it in my .lldbinit file.

<code class="bash">command alias alt expr -l objc++ -O --[[UIWindow keyWindow] _autolayoutTrace]  

Now you can just type alt and get the same output from the debugger.

You’ll notice that I am throwing this out for the entire contents of the keyWindow. I haven’t been able to find a way to pinpoint it down a single property such as self.view, so if you have any feedback on that, please share!

If you’re mixing Objective-C and Swift, you likely already have a bridging header. You can bridge add a category on UIView that exposes the recursiveDescription and _autolayoutTrace methods to Swift.

<code class="objectivec">#ifdef DEBUG

@interface UIView (LayoutDebugging)

#pragma clang push

#pragma clang diagnostic ignored “-Wincomplete-implementation”

- (id)recursiveDescription;

- (id)_autolayoutTrace;

#pragma clang pop

@end

#endif

And the implementation file.

#import “UIView+LayoutDebugging.h”

#ifdef DEBUG

@implementation UIView (LayoutDebugging)

// Nothing to see here!

@end

#endif

Let’s walk through this. You’ll notice that I have the entire thing wrapped in an #ifdef DEBUG statement because I am working with private APIs that I presume the App Store usage checker would flag and reject your app against. With the #ifdef, I am saying that it should only be included on development builds. Apple will have no idea what abuses we are committing since it will never make it to the release builds!

The other atrocity I am committing in this file is the use of #pragma clang diagnostic to tell the compiler to ignore any ‘uninmplemented method’ warnings that will pop-up from not being able to find an implementation for the two methods we defined in our category. Since they exist as private API, we don’t need to reimplement them.

Now if you break in a Swift frame with LLDB and try to call self.view._autolayoutTrace() you’ll get an output you expected.

Happy debugging!

If you’ve found this post useful, and want to learn more about how to best take advantage of Auto Layout in your OS X and iOS apps, be sure to purchase my new book Achieving Zen With Auto Layout

Read more about. . .

Learning How To Make Sausage

Let’s imagine there is someone out there who watched last week’s WWDC keynote and thought to themselves, “This is it! Now! Now is the time for me to learn to program and build an iOS app!”

Nevermind that they are about 6 years late to gold rush, it’s an exciting proposition. Programming is fun! I come from a family of builders. The only difference between my father and grandfathers is they built homes with hammers. I sit in front of a keyboard all day typing and looking at cat GIFs.

I digress. You want to learn to be an iOS developer. What are you supposed to do? Aaron Hillegass (whose books I credit with teaching me this stuff way back when he was the only person writing about Cocoa development) says you should learn Objective-C. Ash Furrow and a few others say you should learn Swift because Objective-C is too hard.

Guess what? It doesn’t matter what language you want to learn.

If you want to be an iOS developer you realistically have four options:

  1. Objective-C: old faithful.
  2. Swift: New hotness.
  3. Xamarin: The crazy kids in the corner who want to use C#.
  4. RubyMotion: Know Ruby? Tired of arguing with DHH about whether tests are dead? You too can build an iOS app.

I’d lean towards choosing one of the first two options because they are first-party solutions provided directly by Apple, but the language you choose to learn matters little compared to learning the frameworks. The Cocoa Touch frameworks have always been the secret sauce. Whether you’re using Objective-C, Swift, C#, or Ruby you’re still going to have to learn how to use a UIButton and a UITableView.

Will you be more of an iOS developer because you took the time to learn Objective-C and it’s 20+ years of history versus Swift and its eleven days? Nope. Your customers care about what’s on the surface of your app: does it look, interact, and feel like an iOS app. If you can do that, the language doesn’t matter.

There is no right answer to this question. Choose what the language that speaks to you and then go build something awesome.

Read more about. . .