Skip to content

Category: Swift

Keep your debug toolkit handy but hidden using conditional compilation

When you’ve been working on an app for a while, especially as it gets large, you often start to include snippets of code in the app that have been useful for debugging your app in the past. Such debugging code may be as simple as log statements, to as complex as adding full screens to your interface, activated by controls that you add to your interface for debugging only.

Such tools become an integral part of your debugging environment; you don’t want to throw them out. But do you really want to ship those in your app? It makes your app bigger and slower. You could comment them out before you release, but after a marathon debug session, do you trust that you’ll comment out again all of the debugging tools you enabled?

How can I keep my debugging addons, but ensure they aren’t in the version I deploy to the App Store?

There is a way: you can use a feature of Swift called conditional compilation to enable debugging code on your debug build. If you still have Objective-C code, you’re still in luck: a similar feature called preprocessor macros can provide the same functionality.

Porting to Swift? Do it Gradually Using Extensions: Part 3

As a refresher from Part 1 and Part 2, we’re trying to make the process of porting Objective-C to Swift code more gradual by porting classes method by method using Swift extensions. This is very helpful in keeping with the idea of “When it comes to porting, smaller steps are better.” In this part, we’ll cover something I discovered when porting my custom UIKit code to Swift.

Porting UIViews and UIViewControllers is relatively straightforward using the techniques we’ve already discussed. But delegates, your most common extension point for UIViews and UIViewControllers, can be a different story.

You do the easy thing: take that first method from the delegate protocol and move it to your Swift extension. You will probably get away with this for a while, until you move a method, and Xcode suddenly expresses its unhappiness:

In this case, long ago, Apple decided to “help” you by providing a default implementation for certain methods of UIKit delegates. Whether this was a good idea in the first place is a topic for another article, but when porting the method to Swift, this causes nothing but problems.

Porting to Swift? Do it Gradually Using Extensions: Part 2

As a refresher from Part 1, we’re trying to make the process of porting Objective-C to Swift code more gradual by porting classes method by method using Swift extensions. This is very helpful in keeping with the idea of “When it comes to porting, smaller steps are better.”

This only gets us so far, though.

Some of the classes you want to port are going to contain business logic for your apps. Model data, calculations on that model data, transformations, etc.

Unfortunately, you cannot move those properties to your extension; extensions don’t support adding stored properties to a class.

What does that mean? You can’t use Swift-only types for your properties, such as structs, enums, Swift arrays, optionals, etc., because they need to be accessible from both Objective-C and Swift.

Does that mean I’m stuck with ugly Objective-C types like NSArray, NSDictionary, etc. in our Swift code, until the entire class is ported?

Thankfully not. While you can’t add stored properties in an extension, you can add computed properties in an extension. By creating computed properties that bridge between the Objective-C properties and a Swift representation of that property, you can still port your class method by method, while still writing your new Swift methods using all of the power of the Swift type system.

Porting to Swift? Do it Gradually Using Extensions: Part 1

Despite the fact that Swift has been available to iOS developers for over 4 years now, it’s likely that many long-lived apps still have Objective-C code in them. To keep things up to date, and to take advantage of the more modern Swift language, you will need to port those at least some of those classes to Swift.

You are instantly drawn to your small, simple classes, and you think, “Sure, those won’t be a problem at all. I could knock these out in a couple hours a piece.”

But then you open up one of your large classes. And you freeze.

You know which one. Every codebase has (at least) one. It is one of the core classes of the app: hundreds (or thousands…) of lines of code, many dependencies on other classes in your codebase. It’s a core part of the app; porting this class and testing that the porting doesn’t completely break everything else could takes weeks. Nobody has time for “weeks” anymore.

So you surrender, and those big, hairy Objective-C classes stay big, hairy Objective-C.

It saves unnecessary rework to only refactor code that you are actually changing for another reason. But if you’re only changing one method, you don’t want to port the rest of the class you aren’t touching, because it means extra coding work, extra testing work, extra review work…

Is there a way to port Swift like this, method by method, property by property? There is, by writing Swift extensions for your Objective-C classes.

When is a Bool not a Bool?

This is a silly question — or rather, it should be a silly question — but it’s going to bite you sometimes when you integrate Objective-C and Swift code together (*cough* UIKit).

You will try to use what you think is a Bool from an Objective-C API, and suddenly you’re getting this compile error:

This is a Boolean value; why can’t I use this @($^ thing as a Bool?

Normally the standard types play nice between Objective-C and Swift. But Bools are an unusual case that require a non-obvious solution.