Initial trip ups with Swift

Important things to avoid when starting out

This week at WWDC 2014 saw Apple introduce the entirely new programming language Swift to program. I’ve only played around with it a little bit, but I’ve already come upon a few little things that left me stuck.

Before detailing the trip ups I’ve encountered, I have to say that the fact that Apple managed to keep this completely under wraps with no leaks is incredible in and of itself. There may have actually been a little hint that we all missed a few years ago. On Monday after the announcement, I went on Github to see if any Swift projects existed. There was one at https://github.com/a_user/swifter (its gone now):

I covered up the user who created the repo, I figure they wanted it down for a reason

It looks like this is an early version of Swift, as this syntax is not quite what it is today.

Anyway, after playing around with Swift a little bit, I think I like it, though I still have some doubts. I’ll leave a more detailed opinion about the language as a whole for later on when I have more experience with it. Here are the things that tripped me up most when I started playing around with Swift, hopefully someone else will find them helpful when getting started.

What tripped me up

These are likely all temporary problems and will hopefully be fixed soon, but as of now they can definitely trip a newcomer to Swift up.

Static variables

Swift doesn’t allow static variables within a method. Instead, they allow static variables within an enum or struct and a variation of static variables called class variables within classes.

This realistically should look like this in classes then:

class var myStaticVar: MyStaticVarClass? = nil

Unfortunately, if you build a Swift file with this line, you’ll get the error

Class variables are not yet supported

This sucks mostly because if means singletons can’t be implemented right now, at least in the normal way, which is a pretty serious limitation.

Edit: Github user hpique has a repository detailing some of the ways to implement a singleton in Swift that avoid this lack of class variables.

Swift classes with no superclass

In order to allow Swift classes, enums, etc be accessible in Objective-C files, Xcode will on-build generate a file YourProject-Swift.h that you can then import into Objective-C files. In this file, each Swift class will get a generated @interface along these lines:

SWIFT_CLASS(“_DFSGProjectName99ClassName”)
@interface SwiftClass : SwiftSuperClass
@property (nonatomic) NSObject * swiftProperty;
- (void)swiftMethod;
@end

Side note: this is a pretty cool way to see how Swift code translates to Objective-C code. Changing the method definitions in the Swift file allows you to see the direct mapping of Swift types to Objective-C types (its especially cool to see how closures are mapped to blocks).

In The Swift Programming Language, Apple says Swift classes don’t require an explicit superclass:

There is no requirement for classes to subclass any standard root class, so you can include or omit a superclass as needed.

Despite this, if you do not explicitly state the superclass of a class, Xcode will not generate @interfaces for that class. This isn’t very intuitive, as one would think Apple could assume that Swift classes without explicit superclasses subclass NSObject. Its an easy fix, as to get around this, just state the superclass of Swift classes to be NSObject — class Class: NSObject — if you intend on accessing the class in Objective-C files and want the @interface to be automatically generated.

Edit: Apple actually does mention this, I just missed it on my first run through of the docs:

To make your Swift class accessible and usable back in Objective-C, make it a descendant of an Objective-C class or mark it with the @objc attribute.

@class in Objective-C headers

Apple provides a nice little file to import Objective-C files into Swift files called ProjectName-Briding-Header.h. In this file, you simply import the headers of Objective-C files you want accessible in Swift files, and they’ll magically become accessible. Important to know is that this file does not care about @class statements in header files you import.

As an example of why this is a problem, take AFNetworking’s AFHTTPClient. You can add #import “AFHTTPClient.h” to the Bridging Header, but some of AFHTTPClient’s methods will still be mysteriously unavailable to Swift files. getPath… is one such example. The reason for this unavailability is that getPath mentions AFHTTPRequestOperation in its method signature. AFHTTPClient does not import AFHTTPRequestOperation in its header file, but rather uses @class. This apparently confuses Swift, leaving it unable to figure out what exactly AFHTTPRequestOperation is, and so Swift simply doesn’t make the methods involving it available.

In order to use these methods in Swift files, you must explicitly import AFHTTPRequestOperation in the Bridging Header. That will allow Swift to figure out what AFHTTPRequestOperation is and make any methods that include it in their signatures available for use in Swift code.

(Edit) Lack of class property

If you look at the the Objective-C header of NSObject, you’ll see the lines:

+ (Class)superclass;
+ (Class)class;

In Swift, there’s only one line:

class func superclass() -> AnyClass!

For whatever reason, Swift objects do not have a class property. I know there has to be another way to figure out the class of a certain instance, but I haven’t found it yet.

(Edit) “Expected a type” error in Project-Header.h

Lets say you import AFNetworking in the Bridging Header and declare a method in a Swift class like this:

func doSomething(#op: AFHTTPRequestOperation, response: AnyObject) { }

In the generated Project-Swift.h, this will translate to:

- (void)doSomethingWithOp:(AFHTTPRequestOperation *)op response:(id)response;

Unfortunately, Project-Swift.h does not import the Bridging Header. This means that Project-Swift.h doesn’t know what AFHTTPRequestOperation is, so you’ll get the error “Expected a type”. A non-ideal fix that at least works for now is to import the Bridging Header into your precompiled header (.pch).

Final thoughts

I’m sure I’ll encounter some more quirks in the coming days as I mess around with Swift more, but for now these are the big ones I’m aware of. Besides these little trip ups, I’m really enjoying learning Swift. I think that its going to be an incredible addition to iOS developer tools.