Appendix A. C, Objective-C, and Swift - iOS 8 Programming Fundamentals with Swift (2014)

iOS 8 Programming Fundamentals with Swift (2014)

Appendix A. C, Objective-C, and Swift

You are an iOS programmer, and you’ve chosen to adopt Apple’s new language, Swift. And this means that you’ll never have to concern yourself with Apple’s old language, Objective-C, right? Wrong.

Objective-C is not dead. Far from it. You may be using Swift, but Cocoa is not. Programming iOS involves communicating with Cocoa and its supplementary frameworks. The APIs for those frameworks are written in Objective-C — or in its underlying base language, C. Messages that you send to Cocoa using Swift are being translated for you into Objective-C. Objects that you send and receive back and forth across the Swift/Objective-C bridge are Objective-C objects. Some objects that you send from Swift to Objective-C are even being translated for you into other object types, or into nonobject types.

You need to understand what Objective-C expects from you when you are sending messages across the language bridge. You need to know what Objective-C is going to do with those messages. You need to know what is coming from Objective-C, and how it will be represented in Swift. Some APIs cannot be satisfactorily used with Swift alone, so your app may even have to include some Objective-C code.

This appendix summarizes certain linguistic features of C and Objective-C, and describes how Swift interfaces with those features. I do not explain here how to write Objective-C! For example, I’ll talk about Objective-C methods and method declarations, because you need to know how to call an Objective-C method from Swift; but I’m not going to explain how to call an Objective-C method in Objective-C. Earlier editions of this book teach C and Objective-C systematically and in detail, and I strongly recommend consulting one for full information about those languages.

The C Language

Objective-C is a superset of C; to put it another way, C provides the linguistic underpinnings of Objective-C. Everything that is true of C is true also of Objective-C. It is possible, and often necessary, to write long stretches of Objective-C code that are, in effect, pure C. Some of the Cocoa APIs are written in C. Therefore, in order to know about Objective-C, it is necessary to know about C.

C statements, including declarations, must end in a semicolon. Variables must be declared before use. Variable declaration syntax is: a data type name followed by the variable name, optionally followed by assignment of an initial value:

int i;

double d = 3.14159;

The C typedef statement starts with an existing type name and defines a new synonym for it:

typedef double NSTimeInterval;

C Data Types

C is not an object-oriented language; its data types are not objects (they are scalars). The basic built-in C data types are all numeric: char (one byte), int (four bytes), float and double (floating-point numbers), and varieties such as short (short integer), long (long integer), unsigned short, and so on. Objective-C adds NSInteger, NSUInteger (unsigned), and CGFloat. The C bool type is actually a numeric, with zero representing false; Objective-C adds BOOL, which is also a numeric. The C native text type (string) is actually a null-terminated array of char.

Swift explicitly supplies numeric types that interface directly with C numeric types, even though Swift’s types are objects and C’s types are not. Swift type aliases provide names that correspond to the C type names: a Swift CBool is a C bool, a Swift CChar is a C char (a Swift Int8), a Swift CInt is a C int (a Swift Int32), a Swift CFloat is a C float (a Swift Float), and so on. Swift Int interchanges with NSInteger; Swift UInt interchanges with NSUInteger. Swift Bool interchanges with Swift ObjCBool, which represents Objective-C BOOL. CGFloat is adopted as a Swift type name.

A major difference between C and Swift is that C (and therefore Objective-C) implicitly coerces when values of different numeric types are assigned, passed, or compared to one another; Swift doesn’t, so you must coerce explicitly to make types match exactly.

The native C string type, a null-terminated array of char, is typed in Swift, for reasons that will be clear later, as UnsafePointer<Int8> (recall that Int8 is CChar). A C string can’t be formed as a literal in Swift; but it usually doesn’t need to be, because you can pass a Swift String where a C string is expected:

let q = dispatch_queue_create("MyQueue", nil)

If you need to create a C string variable, the NSString UTF8String property and cStringUsingEncoding: method can be used to form a C string. Alternatively, you can use the Swift String withCString instance method; the syntax is a little tricky:

var cs : UnsafePointer<Int8> = "howdy".withCString { $0 }

In the other direction, a C string can be rendered into a Swift String (wrapped in an Optional) by way of the Swift String static method fromCString.

C Enums

A C enum is numeric; values are some form of integer, and can be implicit (starting from 0) or explicit. Enums arrive in various forms into Swift, depending on exactly how they are declared. Let’s start with the simplest (and oldest) form:

typedef uint32_t ABRecordType;

enum {

kABPersonType = 0,

kABGroupType = 1,

kABSourceType = 2

};

The enum declaration can specify the integer type further; this one doesn’t, so the names kABPersonType and so on arrive into Swift as Int constants.

This enum declaration, however, is accompanied by a typedef statment providing an associated type name and specifying a numeric type. The name ABRecordType is not formally tied to this enum in any way; but in a declaration where a value of this enum is expected or returned, ABRecordType will appear. In Swift, ABRecordType is type aliased to UIInt32, corresponding to uint32_t. But I have just finished saying that kABPersonType is an Int. In Swift, therefore, we have an impedance mismatch! You will have to resolve it by coercion:

let type = ABRecordGetRecordType(snidely) // type is an ABRecordType

if Int(type) == kABPersonType { // to compare with Int, must coerce

println("it is a person")

}

Starting in Xcode 4.4, a new C enum notation was introduced, based on the NS_ENUM macro:

typedef NS_ENUM(NSInteger, UIStatusBarAnimation) {

UIStatusBarAnimationNone,

UIStatusBarAnimationFade,

UIStatusBarAnimationSlide,

};

That notation explicitly specifies the integer type and associates a type name with this enum as a whole. Swift can read that notation, and imports an enum declared this way as a Swift enum, with the name and type intact. Moreover, Swift automatically subtracts the common prefix from the imported case names:

enum UIStatusBarAnimation : Int {

case None

case Fade

case Slide

}

Starting in Swift 1.2, the bridge can be crossed in the other direction: a Swift enum with an Int raw value type can be exposed to Objective-C using the @objc attribute. Thus, for example:

@objc enum Star : Int {

case Blue

case White

case Yellow

case Red

}

Objective-C sees that as an NS_ENUM enum with type NSInteger and enumerand names StarBlue, StarWhite, and so on.

There is another variant of C enum notation, based on the NS_OPTIONS macro, suitable for bitmasks:

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {

UIViewAutoresizingNone = 0,

UIViewAutoresizingFlexibleLeftMargin = 1 << 0,

UIViewAutoresizingFlexibleWidth = 1 << 1,

UIViewAutoresizingFlexibleRightMargin = 1 << 2,

UIViewAutoresizingFlexibleTopMargin = 1 << 3,

UIViewAutoresizingFlexibleHeight = 1 << 4,

UIViewAutoresizingFlexibleBottomMargin = 1 << 5

};

Swift imports an enum declared this way as a Swift struct adopting the RawOptionSetType protocol. Such a struct has a rawValue instance property holding the underlying integer. An instance can be created by calling its init(rawValue:) initializer, but there is also an initializer with no external parameter name, which will usually be preferable. The C enum case names are represented by static properties, each of whose values is an instance of this struct; the names of these static properties are imported with the common prefix subtracted:

struct UIViewAutoresizing : RawOptionSetType {

init(_ rawValue: UInt)

init(rawValue: UInt)

static var None: UIViewAutoresizing { get }

static var FlexibleLeftMargin: UIViewAutoresizing { get }

static var FlexibleWidth: UIViewAutoresizing { get }

static var FlexibleRightMargin: UIViewAutoresizing { get }

static var FlexibleTopMargin: UIViewAutoresizing { get }

static var FlexibleHeight: UIViewAutoresizing { get }

static var FlexibleBottomMargin: UIViewAutoresizing { get }

}

Thus, for example, when you say UIViewAutoresizing.FlexibleLeftMargin, it looks as if you are initializing a case of a Swift enum, but in fact this is an instance of the UIViewAutoresizing struct, whose rawValue property has been set to the value declared by the original C enum — which, for .FlexibleLeftMargin, is 1<<0. Because a static property of this struct is an instance of the same struct, you can, as with an enum, omit the struct name when supplying a static property name where the struct instance is expected:

self.view.autoresizingMask = .FlexibleWidth

Moreover, integer bitwise operations can be applied to an instance of this struct — thus permitting you to combine instances with the bitwise-or operator to form the bitmask:

self.view.autoresizingMask = .FlexibleWidth | .FlexibleHeight

TIP

Where an NS_OPTIONS enum is expected in Objective-C, you pass 0 to indicate that no options are provided. In Swift, where a corresponding struct is expected, you can pass nil as a shortcut.

Many common lists of alternatives, unfortunately, are not implemented as enums in the first place. This is not problematic, but it is inconvenient. For example, the names of the AVFoundation audio session categories are just NSString constants:

NSString *const AVAudioSessionCategoryAmbient;

NSString *const AVAudioSessionCategorySoloAmbient;

NSString *const AVAudioSessionCategoryPlayback;

// ... and so on ...

Even though this is a list of alternatives with an obvious common prefix, Swift cannot (and does not) magically transform it into an AVAudioSessionCategory enum or struct with abbreviated names. When you want to specify the Playback category, you have to use the whole name,AVAudioSessionCategoryPlayback.

C Structs

A C struct is a compound type whose elements can be accessed by name using dot-notation after a reference to the struct. For example:

struct CGPoint {

CGFloat x;

CGFloat y;

};

typedef struct CGPoint CGPoint;

(The typedef in the last line allows C programs to use the term CGPoint as the name of this type instead of the more verbose struct CGPoint.) After that declaration, it becomes possible to talk like this in C:

CGPoint p;

p.x = 100;

p.y = 200;

A C struct arrives wholesale into Swift as a Swift struct, which is thereupon endowed with Swift struct features. Thus, for example, CGPoint in Swift has x and y CGFloat instance properties, as you would expect; but it also magically acquires the memberwise initializer! Extensions can supply additional features, and the Swift CoreGraphics header adds a few to CGPoint:

extension CGPoint {

static var zeroPoint: CGPoint { get }

init()

init(x: Int, y: Int)

init(x: Double, y: Double)

}

As you can see, a Swift CGPoint has additional memberwise initializers accepting Int or Double arguments, along with two ways of making a zero CGPoint, CGPoint.zeroPoint and CGPoint(). CGSize is treated similarly. CGRect is particularly well endowed with added methods and properties in Swift; these do not allow you to do anything that you couldn’t do with the built-in C functions provided by the Core Graphics framework for manipulating a CGRect, but they do allow you to do those things in a Swiftier way.

C Pointers

A C pointer is an integer designating the location in memory (the address) where the real data resides. Allocating and disposing of that memory is a separate matter. The declaration for a pointer to a data type is written with an asterisk after the data type name; a space can appear on either or both sides of the asterisk. These are equivalent declarations of a pointer-to-int:

int *intPtr1;

int* intPtr2;

int * intPtr3;

The type name itself is int* (or, with a space, int *). Objective-C, for reasons that I’ll explain later, uses C pointers heavily, so you’re going to be seeing that asterisk a lot if you look at any Objective-C.

A C pointer arrives into Swift as an UnsafePointer or, if writable, an UnsafeMutablePointer; this is a generic, and is specified to the actual type of data pointed to. (A pointer is “unsafe” because Swift isn’t managing the memory for, and can’t even guarantee the integrity of, what is pointed to.)

For example, here’s a C function declaration; I haven’t discussed C function syntax yet, but just concentrate on the types which precede each parameter name:

void CGRectDivide(CGRect rect,

CGRect *slice,

CGRect *remainder,

CGFloat amount,

CGRectEdge edge)

The term void means that this function returns no value. CGRect and CGRectEdge are C structs; CGFloat is a basic numeric type. The phrases CGRect *slice and CGRect *remainder, despite the position of the space, state that slice and remainder are both CGRect* — that is, pointer-to-CGRect. The Swift translation of that declaration looks like this:

func CGRectDivide(rect: CGRect,

slice: UnsafeMutablePointer<CGRect>,

remainder: UnsafeMutablePointer<CGRect>,

amount: CGFloat,

edge: CGRectEdge)

UnsafeMutablePointer in this context is used like a Swift inout parameter: you declare and initialize a var of the appropriate type beforehand, and then pass its address as argument by way of the & prefix operator. When you pass the address of a reference in this way, you are in fact creating and passing a pointer:

var arrow = CGRectZero

var body = CGRectZero

CGRectDivide(rect, &arrow, &body, Arrow.ARHEIGHT, .MinYEdge)

In C, to access the memory pointed to by a pointer, you use an asterisk before the pointer’s name: *intPtr is “the thing pointed to by the pointer intPtr.” In Swift, you use the pointer’s memory property.

In this example, we receive a stop parameter typed originally as a BOOL*, a pointer-to-BOOL; in Swift, it’s an UnsafeMutablePointer<ObjCBool>. To set the BOOL at the far end of this pointer, we set the pointer’s memory (mas is an NSMutableAttributedString):

mas.enumerateAttribute("HERE", inRange: r, options: nil) {

value, r, stop in

if let value = value as? Int {

if value == 1 {

stop.memory = true

}

}

}

The most general type of C pointer is pointer-to-void (void*), also known as the generic pointer. The term void here means that no type is specified; it is legal in C to use a generic pointer wherever a specific type of pointer is expected, and vice versa. In effect, pointer-to-void casts away type checking as to what’s at the far end of the pointer. This will appear in Swift as a pointer generic specified to Void — typically, UnsafeMutablePointer<Void>, or its equivalent UnsafeMutablePointer<()>. In general, when you encounter pointers of this type, if you need to access the underlying data, you’ll start by coercing to an UnsafeMutablePointer generic specified to the underlying type.

C Arrays

A C array contains a fixed number of elements of a certain data type. Under the hood, it is a block of memory sized to accommodate this number of elements of this data type. For this reason, the name of an array in C is the name of a pointer — to the first element of the array. For example, ifarr has been declared as an array of int, the term arr can be used wherever a value of type int* (a pointer-to-int) is expected. The C language will indicate an array type either by appending square brackets to a reference or as a pointer.

(This also explains why string methods involving C strings type those C strings in Swift as an unsafe pointer to Int8: a C string is an array of char, and an Int8 is a char.)

For example, the C function CGContextStrokeLineSegments is declared like this:

void CGContextStrokeLineSegments (

CGContextRef c,

const CGPoint points[],

size_t count

);

The second parameter is a C array of CGPoints; that’s what the square brackets tell you. A C array carries no information about how many elements it contains, so to pass this C array to this function, you must also tell the function how many elements the array contains; that’s what the third parameter is for. A C array of CGPoint is a pointer to a CGPoint, so this function’s declaration is translated into Swift like this:

func CGContextStrokeLineSegments(

c: CGContext!,

points: UnsafePointer<CGPoint>,

count: Int)

To call this function and pass it a C array of CGPoints, it would appear that you need to make a C array of CGPoints. A C array is not, by any stretch of the imagination, a Swift array; so how on earth will you do this? Surprise! You don’t have to. Even though a Swift array is not a C array, you can pass a pointer to a Swift array here. In fact, you don’t even need to pass a pointer; you can pass a reference to a Swift array itself. And since this is not a mutable pointer, you can declare the array with let; indeed, you can even pass a Swift array literal! No matter which approach you choose, Swift will convert to a C array for you as the argument crosses the bridge from Swift to C:

let c = UIGraphicsGetCurrentContext()

let arr = [CGPoint(x:0,y:0),

CGPoint(x:50,y:50),

CGPoint(x:50,y:50),

CGPoint(x:0,y:100),

]

CGContextStrokeLineSegments(c, arr, 4)

However, you can form a C array if you really want to. To do so, you must first set aside the block of memory yourself: declare an UnsafeMutablePointer of the desired type, calling the static method alloc with the desired number of elements. You can then initialize the memory by writing the elements directly into it with subscripting, as if an UnsafeMutablePointer were an array. Finally, since the UnsafeMutablePointer is a pointer, you pass it, not a pointer to it, as argument:

let c = UIGraphicsGetCurrentContext()

var arr = UnsafeMutablePointer<CGPoint>.alloc(4)

arr[0] = CGPoint(x:0,y:0)

arr[1] = CGPoint(x:50,y:50)

arr[2] = CGPoint(x:50,y:50)

arr[3] = CGPoint(x:0,y:100)

CGContextStrokeLineSegments(c, arr, 4)

The same convenient subscripting is available when you receive a C array. For example:

let col = UIColor(red: 0.5, green: 0.6, blue: 0.7, alpha: 1.0)

let comp = CGColorGetComponents(col.CGColor)

After that code, comp is typed as an UnsafePointer to CGFloat. This really means that it’s a C array of CGFloat — and so you can access its elements by subscripting:

let red = comp[0]

let green = comp[1]

let blue = comp[2]

let alpha = comp[3]

C Functions

A C function declaration starts with the return type (which might be void, meaning no returned value), followed by the function name, followed by a parameter list, in parentheses, of comma-separated pairs consisting of the type followed by the parameter name. The parameter names are purely internal; you won’t use them when calling a C function.

Here’s the C declaration for CGPointMake, which returns an initialized CGPoint:

CGPoint CGPointMake (

CGFloat x,

CGFloat y

);

And here’s how to call it in Swift:

let p = CGPointMake(50,50)

In Objective-C, where CGPoint is not an object, CGPointMake is the main way to create a CGPoint. Swift, as I’ve already mentioned, supplies initializers — though I personally still prefer CGPointMake.

In C, a function has a type based on its signature, and the name of a function is a reference to the function, and so it is possible to pass a function — sometimes referred to as a pointer-to-function — by using the function’s name where a function of that type is expected. In a declaration, a pointer-to-function may be symbolized by an asterisk in parentheses. For example, the first parameter to the NSArray method sortedArrayUsingFunction:context: is a pointer-to-function:

- (NSArray *)sortedArrayUsingFunction:

(NSInteger (*)(id, id, void *)) comparator

context:(void *)context;

I haven’t talked about Objective-C method declaration syntax yet, but just concentrate on the expression in parentheses before comparator:

(NSInteger (*)(id, id, void *)) comparator

That tells you, in the rather tortured syntax that C uses for these things, that comparator is a pointer to a function taking three parameters (typed id, id, and void*) and returning an NSInteger.

In Objective-C you could call sortedArrayUsingFunction:context: by defining the C function and then passing it, like this (assume that arr is an NSArray of NSStrings):

NSInteger sortByLastCharacter(id string1, id string2, void* context) {

NSString* s1 = string1;

NSString* s2 = string2;

NSString* string1end = [s1 substringFromIndex:[s1 length] - 1];

NSString* string2end = [s2 substringFromIndex:[s2 length] - 1];

return [string1end compare:string2end];

}

NSArray* arr2 =

[arr sortedArrayUsingFunction:sortByLastCharacter context:nil];

In that code, the first line declares sortByLastCharacter as a C function and defines the body of the function; the last line then passes the sortByLastCharacter function as the first argument to sortedArrayUsingFunction:context:.

In Swift, however, you can’t do that — because you cannot define a C function. Therefore you can’t supply a C pointer-to-function argument without the function already existing somewhere else. Nor can you, in Swift, form a C pointer-to-function; you have to get the pointer from somewhere else as well. In the case of sortedArrayUsingFunction:context:, that’s no disaster, because there are other ways to sort an array, including the Swift sorted method which takes a Swift function. But you may encounter other situations where a C function is expected, and then you may have no recourse but to write a helper method in Objective-C to supply it.

For example, before playing an iOS system sound (a “beep”) by calling AudioServicesPlaySystemSound, you need to call AudioServicesAddSystemSoundCompletion, which takes as its fourth parameter a C function that will be called when the sound finishes playing, and whose job is to dispose of the system sound’s memory. But you can’t create that C function, or form a pointer to it, in Swift. My solution is an Objective-C class whose implementation consists of the C function along with an Objective-C method that returns a reference to it:

void soundFinished (SystemSoundID snd, void* context) {

AudioServicesRemoveSystemSoundCompletion(snd);

AudioServicesDisposeSystemSoundID(snd);

}

- (AudioServicesSystemSoundCompletionProc) completionHandler {

return soundFinished;

}

My Swift code instantiates that Objective-C class, storing the instance in a property, self.helper. Now I can obtain the C pointer-to-function from self.helper by calling its completionHandler method, and so I can play a system sound in Swift:

let sndurl = NSBundle.mainBundle().URLForResource(

"test", withExtension: "aif")

var snd : SystemSoundID = 0

AudioServicesCreateSystemSoundID(sndurl, &snd)

AudioServicesAddSystemSoundCompletion(

snd, nil, nil, self.helper.completionHandler(), nil)

AudioServicesPlaySystemSound(snd)

Objective-C

Objective-C is built on the back of C. It adds some syntax and features, but it continues to use C syntax and data types, and remains C under the hood.

Unlike Swift, Objective-C has no namespaces. For this reason, different frameworks distinguish their contents by starting their names with different prefixes. The “CG” in “CGFloat” stands for Core Graphics, because it is declared in the Core Graphics framework. The “NS” in “NSString” stands for NeXTStep, a historical name for the framework that later became Cocoa. And so on.

Objective-C Objects and C Pointers

All the C data types and syntax of C are part of Objective-C. But Objective-C is also object-oriented, so it needs a way of adding objects to C. It does this by taking advantage of C pointers. C pointers accommodate having anything at all at the far end of the pointer; management of whatever is pointed to is a separate matter, and that’s just what Objective-C takes care of. Thus, Objective-C object types are expressed using C pointer syntax.

For example, here’s the Objective-C declaration for the addSubview: method:

- (void)addSubview:(UIView *)view;

I haven’t discussed Objective-C method declaration syntax yet, but focus on the type declaration for the view parameter, in parentheses: it is UIView*. This appears to mean “a pointer to a UIView.” It does mean that — and it doesn’t. All Objective-C object references are pointers. Thus, the fact that this is a pointer is merely a way of saying it’s an object. What’s at the far end of the pointer is a UIView instance.

The Swift translation of this method declaration, however, doesn’t appear to involve any pointers:

func addSubview(view: UIView)

In general, in Swift, you will simply pass a reference to a class instance where Objective-C expects a class instance; the fact that an asterisk is used in the Objective-C declaration to express the fact that this is an object won’t matter. What you pass as argument when calling the addSubview:method from Swift is a UIView instance. There is a sense in which you are passing a pointer when you pass a class instance — because class instances are reference types. Thus, a class instance is actually seen the same way by both Swift and Objective-C. The difference is that Swift doesn’t use pointer notation to refer to object types.

On the other hand, there is such a thing as an explicit pointer to an Objective-C object, and sometimes you’ll have to deal with one. This situation arises particularly in connection with NSError. A common Cocoa convention is that a method will return an object and will also take a pointer-to-NSError parameter; if there’s a failure, the method returns nil and sets the NSError by indirection. The pointer-to-NSError is thus the Objective-C version of an inout parameter. This convention is so frequently used, in fact, that Swift defines a type alias NSErrorPointer to meanAutoreleasingUnsafeMutablePointer<NSError?>. That’s a pointer to an NSError — an NSError wrapped in an Optional, because it might be necessary to pass nil here. (The “autoreleasing” part of that name has to do with Objective-C memory management; see Chapter 12.)

For example, NSString has an initializer declared in Objective-C like this:

- (instancetype)initWithContentsOfFile:(NSString *)path

encoding:(NSStringEncoding)enc

error:(NSError **)error;

The third parameter is an NSError**. An NSError* is an NSError object, so an NSError** is a pointer to an NSError object. The Swift translation of that declaration looks like this:

convenience init?(contentsOfFile path: String,

encoding enc: UInt,

error: NSErrorPointer)

And you call it just as you would expect — by passing a pointer to an Optional wrapping an NSError:

var err : NSError? = nil

let s = String(contentsOfFile: f, encoding: NSUTF8StringEncoding, error: &err)

If your Swift method receives an NSErrorPointer as a parameter and you want to set it, set its memory property to an NSError instance.

Objective-C Objects and Swift Objects

Objective-C objects are classes and instances of classes. They arrive into Swift more or less intact. You won’t have any trouble subclassing Objective-C classes or working with instances of Objective-C classes. I’ve already talked about how C types, which are not objects, arrive into Swift as objects as well.

Going the other way, however, Swift objects — that is, objects that originate in Swift — are much more powerful and extensive than Objective-C objects, and cannot cross the bridge from Swift to Objective-C unless they are classes or class instances — and even then, Objective-C won’t be able to see properties and methods that use Swift-only types and features. But this is not really a problem, because, in real life, the vast majority of objects that you want to hand over from Swift to Objective-C either will be bridged types or else will have come from Objective-C in the first place.

Thus, for example, Objective-C can’t see a Swift struct; but it can see a struct like CGPoint, because CGPoint came from the Objective-C world to start with. You can extend CGPoint, and you might extend it using Swift-only features that Objective-C can’t see. That’s fine, because the only thing you care about when you hand a CGPoint over to Objective-C are its x and y values, which cross the bridge perfectly well.

Similarly, you might extend a UIViewController subclass with methods that use Swift-only features — none of which Objective-C can call. But that’s fine, because you won’t need Objective-C to call those methods. Objective-C can call the UIViewController methods that are declared originally in Objective-C — inherited methods that you have overridden, or methods that you have declared because your UIViewController subclass adopts an Objective-C protocol — and so Cocoa will still work correctly with your UIViewController subclass.

On the whole, therefore, you won’t have to give much thought to the question of whether a Swift object can cross the bridge from Swift to Objective-C; if anything, because of Swift’s automatic bridging, crossing the bridge will actually be easier than if you were working in Objective-C. For example, a Swift Int can be used where an Objective-C object is expected, because Swift will wrap it in an NSNumber for you; in Objective-C, you would have had to remember to wrap an integer in an NSNumber yourself. The following nonclass types are automatically bridged to Objective-C class types when you pass or assign them where Objective-C expects an object:

§ String to NSString

§ Int, UInt, Double, Float, and Bool to NSNumber

§ Array (of bridgeables) to NSArray

§ Dictionary (of bridgeables) to NSDictionary

§ Set (of bridgeables) to NSSet

The only other objects that you will need to expose to Objective-C will be classes and class instances — and in the vast majority of cases, these will either be classes declared in Objective-C or subclasses, declared in Swift, of classes declared in Objective-C. Such objects are visible to Objective-C automatically. For example, your Swift code will always subclass UIViewController, and Objective-C will be able to see your subclass. If you give your subclass additional properties with types that come from or are bridged to Objective-C, Objective-C will also be able to see those properties.

But what if you want to declare a custom class in Swift? If you want Objective-C to be able to see this class and to be able to work compatibly with instances of it, and if you are not subclassing any particular Cocoa class, your first thought should be to subclass NSObject, the Objective-C base class. Now you are subclassing an Objective-C class, so Objective-C can see your subclass. And NSObject is the source of all standard Objective-C class and instance behavior, so your custom class will have complete compatibility with Objective-C.

But let’s say you don’t want to subclass NSObject or any other Objective-C class, but you still want Objective-C to see your class. Then you can use the @objc attribute at the start of the class declaration — or, depending on your needs, it may be sufficient to declare just an individual member, such as a method, with @objc.

Similarly, if you want Objective-C to see a protocol that you declare, you must declare it with @objc (and it will then be a class protocol).

Optionally, when you declare something with @objc, you can add parentheses containing the name by which you want Objective-C to see this thing. You are free to do this even for a class or a class member that Objective-C can see already, as in this example:

@objc(ViewController) class ViewController : UIViewController { // ...

That code demonstrates something that is in fact useful to do. By default, Objective-C sees your class’s name as being namespaced (prefixed) by the module name (typically, the project name). This can wreck the automatic association between a view controller and the eponymous .xib file containing its main view. When you use the @objc(...) syntax, though, the name in parentheses is global, not namespaced, and the automatic association with the .xib file works.

(For the same reason, when you’re translating an existing Objective-C project into Swift, you may want to use @objc(...) syntax to prevent a nib object or an NSCoding archive from losing track of its associated class.)

Objective-C’s id type is a general pointer to an object — the object equivalent of pointer-to-void. (Because id is itself a pointer, a reference declared as id doesn’t use an asterisk; you will probably never see an id*.) Any object type can be assigned or cast to or from an id. Swift’s AnyObject is parallel, and an Objective-C id type declaration is translated into Swift as AnyObject. But where hashability is needed, as for the members of an NSSet or the keys of an NSDictionary, Swift uses NSObject instead.

Objective-C Methods

In Objective-C, method parameters can have names, and the name of a method as a whole is not distinct from the names of the parameters. The parameter names are part of the method name, with a colon appearing where each parameter would need to go. For example, the UIViewController class has an instance method called presentViewController:animated:completion:. That name contains three colons, so this method takes three parameters. Here’s a typical example of calling it in Objective-C:

SecondViewController* svc = [SecondViewController new];

[self presentViewController:svc animated:YES completion:nil];

The declaration for an Objective-C method has three parts:

§ Either + or -, meaning that the method is a class method or an instance method, respectively.

§ The data type of the return value, in parentheses. It might be void, meaning no returned value.

§ The name of the method, split after each colon so as to make room for the parameters. Following each colon is the data type of the parameter, in parentheses, followed by a placeholder name for the parameter.

So, for example, the Objective-C declaration for the UIViewController instance method presentViewController:animated:completion: is:

- (void)presentViewController: (UIViewController *)viewControllerToPresent

animated: (BOOL)flag

completion: (void (^)(void))completion;

(That mysterious-looking third parameter type is a block; I’ll discuss blocks later.)

Recall that Swift methods, by default, externalize all their parameter names except the first. In Swift, therefore, an Objective-C method declaration is translated into a function declaration, as follows:

§ The stuff before the first colon becomes the name of the function.

§ The stuff before each of the other colons becomes an external parameter name. The first parameter has no external name.

§ The names after the parameter types become internal (local) parameter names. If an external parameter name would be the same as the internal (local) name, there is no need to repeat it.

Thus, the Swift translation of that Objective-C method declaration looks like this:

func presentViewController(viewControllerToPresent: UIViewController,

animated flag: Bool,

completion: (() -> Void)?)

When you call a method in Swift, the internal parameter names don’t come into play:

let svc = SecondViewController()

self.presentViewController(svc, animated: true, completion: nil)

When you implement a method declared in Objective-C, it will either be because you’re obeying an adopted protocol or because you’re overriding an inherited method. The internal parameter names are supplied for you by Xcode’s code completion feature — but you are free to change them. The external parameter names, however, must not be changed; they are part of the name of this method!

Thus, if you were to override presentViewController:animated:completion: (you probably wouldn’t, but it isn’t illegal to do so), this would be legal:

override func presentViewController(vc: UIViewController,

animated anim: Bool,

completion handler: (() -> Void)?) {

// ...

}

Unlike Swift, Objective-C does not permit overloading of methods. Two MyClass instance methods called myMethod:, both returning void, one taking a CGFloat parameter and one taking an NSString parameter, and both visible to Objective-C, would be illegal.

Objective-C has its own version of a variadic parameter. For example, the NSArray instance method arrayWithObjects: is declared like this:

+ (id)arrayWithObjects:(id)firstObj, ... ;

Unlike Swift, such methods must somehow be told explicitly how many arguments are being supplied. Many such methods, including arrayWithObjects:, use a nil terminator; that is, the caller supplies nil after the last argument, and the callee knows when it has passed the last argument because it encounters nil. A call to arrayWithObjects: in Objective-C would look something like this:

NSArray* pep = [NSArray arrayWithObjects: manny, moe, jack, nil];

Objective-C cannot call (or see) a Swift method that takes a variadic parameter. Swift, however, can call an Objective-C method that takes a variadic parameter, provided that it is marked NS_REQUIRES_NIL_TERMINATION. arrayWithObjects: is marked in this way, so you can sayNSArray(objects:1, 2, 3) and Swift will supply the missing nil terminator.

Unfortunately, the UIView class method appearanceWhenContainedIn:, even though it is marked in this way, is currently not available in Swift. (I don’t understand the reason for this; I regard it as a bug.) Until Apple provides a replacement API, you’ll have to write an Objective-C helper class if you want to call this method.

Objective-C Initializers and Factories

Objective-C initializer methods are instance methods; actual instantiation is performed using the NSObject class method alloc, for which Swift has no equivalent (and doesn’t need one), and the initializer message is sent to the instance that results. For example, this is how you create a UIColor instance by supplying red, green, blue, and alpha values in Objective-C:

UIColor* col = [[UIColor alloc] initWithRed:0.5 green:0.6 blue:0.7 alpha:1];

The name of that initializer, in Objective-C, is initWithRed:green:blue:alpha:. It’s declared like this:

- (UIColor *)initWithRed:(CGFloat)red green:(CGFloat)green

blue:(CGFloat)blue alpha:(CGFloat)alpha;

In short, an initializer method, to all outward appearances, is just an instance method like any other in Objective-C.

Swift, nevertheless, is able to detect that an Objective-C initializer is an initializer, because the name is special — it starts with init! Therefore, Swift is able to translate an Objective-C initializer into a Swift initializer.

This translation is performed in a special way. Unlike an ordinary method, an Objective-C initializer is translated into Swift with all the parameter names appearing as external names inside the parentheses. At the same time, the external name of the first parameter is subject to some automatic shortening: the word init is stripped from the start of the first parameter name, and the word With, if it appears, is stripped as well. Thus, the external name of the first parameter of this initializer in Swift is red:. If the external names are the same as the internal names, there’s no need to repeat them. Thus, Swift translates Objective-C initWithRed:green:blue:alpha: into the Swift initializer init(red:green:blue:alpha:), which is declared like this:

init(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)

And you’d call it like this:

let col = UIColor(red: 0.5, green: 0.6, blue: 0.7, alpha: 1.0)

There is a second way to create an instance in Objective-C. Very commonly, a class will supply a class method that is a factory for an instance. For example, the UIColor class has a class method colorWithRed:green:blue:alpha:, declared as follows:

+ (UIColor*) colorWithRed: (CGFloat) red green: (CGFloat) green

blue: (CGFloat) blue alpha: (CGFloat) alpha;

Swift detects a factory method of this kind by some pattern-matching rules — a class method that returns an instance of the class, and whose name begins with the name of the class, stripped of its prefix — and translates it as an initializer, stripping the class name (and the With) from the start of the first parameter name. If the resulting initializer exists already, as it does in this example, then Swift treats the factory method as superfluous and suppresses it completely!

Thus, Objective-C colorWithRed:green:blue:alpha: isn’t callable from Swift, because it would be identical to the init(red:green:blue:alpha:) that already exists.

The same name munging operates also in reverse: for example, a Swift initializer init(value:) is visible to and callable by Objective-C under the name initWithValue:.

Selectors

An Objective-C method will sometimes expect as parameter the name of a method to be called later. Such a name is called a selector. For example, the addTarget:action:forControlEvents: method can be called as a way of telling a button in the interface, “From now on, whenever you are tapped, send this message to this object.” The message, the action: parameter, is a selector.

You may imagine that, if this were a Swift method, you’d be passing a function here. A selector, however, is not the same as a function. It’s just a name. Objective-C, unlike Swift, is so dynamic that it is able, at runtime, to construct and send an arbitrary message to an arbitrary object based on the name alone.

But even though it is just a name, a selector is not a string, either. It is, in fact, a separate object type, designated in Objective-C declarations as SEL and in Swift declarations as Selector. In most cases, however, Swift will permit you, as a shortcut, to pass a string where a selector is expected! For example:

b.addTarget(self, action: "doNewGame:", forControlEvents: .TouchUpInside)

Once in a while, you may have to form an actual Selector object, which you can do by coercing a string with the Selector initializer init. In this example, a Selector arrives as a parameter and we need to identify it by comparison. We can’t compare a Selector to a string, so we coerce a string to a Selector so that we can compare two Selectors:

override func canPerformAction(action: Selector,

withSender sender: AnyObject!) -> Bool {

if action == Selector("undo:") { // ...

Now please pretend that I am banging on the table with a large stick and screaming at you: you must get the name of a selector right when you supply it! If you call a method like addTarget:action:forControlEvents: and if you get the method name wrong when you supply theaction: argument, there will be no error or warning at compile time, but Objective-C will later attempt to send this wrong message to your target and your app will crash, along with the dreaded “unrecognized selector” message in the console. This is one of the few situations in which Swift opens itself to the sort of disastrous Objective-C programmer error that, on the whole, it is designed to prevent. (I regard this as a major flaw in the Swift language.)

To get the name right, you need to translate from a Swift method declaration to the Objective-C name of that method. This translation is simple and follows rules that are completely mechanical, but you will be entering the name as a literal string and it is all too easy to make a typing mistake, so be careful:

1. The name starts with everything that precedes the left parenthesis in the method name.

2. If the method takes no parameters, stop. That’s the end of the name.

3. If the method takes any parameters, add a colon.

4. If the method takes more than one parameter, add the external names of all parameters except the first parameter, with a colon after each external parameter name.

Observe that this means that if the method takes any parameters, its Objective-C name will end with a colon. Capitalization counts, and the name should contain no spaces or other punctuation except for the colons.

To illustrate, here are three Swift method declarations, with their Objective-C names given as a string in a comment:

func sayHello() -> String // "sayHello"

func say(s:String) // "say:"

func say(s:String, times n:Int) // "say:times:"

It is possible to crash even though your selector name corresponds correctly to a declared method. For example, here’s a small test class that creates an NSTimer and tells it to call a certain method once per second:

class MyClass {

var timer : NSTimer? = nil

func startTimer() {

self.timer = NSTimer.scheduledTimerWithTimeInterval(1,

target: self, selector: "timerFired:",

userInfo: nil, repeats: true)

}

func timerFired(t:NSTimer) {

println("timer fired")

}

}

There’s nothing wrong with that class structurally; it compiles, and can be instantiated when the app runs. But when we call startTimer, we crash. The problem is not that timerFired doesn’t exist, or that "timerFired:" is not its name; the problem is that Cocoa can’t findtimerFired. This, in turn, is because our class MyClass is a pure Swift class; therefore it lacks the Objective-C introspection and message-sending machinery that would permit Cocoa to see and call timerFired. Any one of the following solutions will solve the problem:

§ Declare MyClass as a subclass of NSObject.

§ Declare MyClass with the @objc attribute.

§ Declare timerFired with the @obc attribute.

§ Declare timerFired with the dynamic keyword. (But this would be overkill; you should reserve use of dynamic for situations where it is needed, namely where Objective-C needs the ability to alter the implementation of a class member.)

CFTypeRefs

CFTypeRef functions are global C functions, and are generally easy to call. The resulting code will usually appear almost as if Swift were C. For memory management of CFTypeRef pseudo-objects, see Chapter 12. Because a CFTypeRef is a pointer, it is interchangeable with C pointer-to-void. And because it is a pointer to a pseudo-object, it is interchangeable with Objective-C id and Swift AnyObject.

Many CFTypeRefs are toll-free bridged to corresponding Objective-C object types. For example, CFString and NSString, CFNumber and NSNumber, CFArray and NSArray, CFDictionary and NSDictionary are all toll-free bridged (and there are many other such pairs). Such pairs are interchangeable by casting, and sometimes you’ll need to do so. Again, this is much easier in Swift than in Objective-C. In Objective-C, you must perform a bridging cast, to tell Objective-C how to manage this object’s memory as it crosses between the memory-managed world of Objective-C objects and the unmanaged world of C and CFTypeRefs. But in Swift, CFTypeRefs are memory-managed, and so there is no need for a bridging cast; you can just cast, plain and simple. In fact, in many cases, Swift will know about the toll-free bridging, and will cast for you, automatically!

For example, in this code from one of my apps, I’m using the ImageIO framework. This framework has a C API and uses CFTypeRefs. CGImageSourceCopyPropertiesAtIndex returns a CFDictionary whose keys are CFStrings. The easiest way to obtain a value from a dictionary is by subscripting, but you can’t do that with a CFDictionary, because it isn’t an object. So I cast it to an NSDictionary — by casting it to a Swift [NSObject:AnyObject]. The key kCGImagePropertyPixelWidth is a CFString, which is not a Hashable (it isn’t a true object at all, and can’t adopt protocols), and hence cannot be used as a Swift dictionary key; but when I try to use it directly in a subscript, Swift allows me to do so, because it casts it for me to an NSString:

let res =

CGImageSourceCopyPropertiesAtIndex(src,0,nil) as [NSObject:AnyObject]

let pw = kCGImagePropertyPixelWidth

let imw = res[pw] as! CGFloat

Blocks

A block is a C language feature introduced by Apple starting in iOS 4. It is very like a C function, but it is not a C function; it behaves as a closure and can be passed around as a reference type. A block, in fact, is parallel to and compatible with a Swift function, and indeed the two are interchangeable: you can pass a Swift function where a block is expected, and when a block is handed to you by Cocoa it appears as a function.

In C and Objective-C, a block declaration is signified by the caret character (^), which appears where a function name (or an asterisk in parentheses) would appear in a C function declaration. For example, the NSArray instance method sortedArrayUsingComparator: takes an NSComparator parameter, which is defined through a typedef like this:

typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);

To read that declaration, it helps to start in the middle and work your way outwards; it says: “NSComparator is the type of a block taking two id parameters and returning an NSComparisonResult.” In Swift, therefore, that typedef is translated like this:

typealias NSComparator = (AnyObject!, AnyObject!) -> NSComparisonResult

In many cases, there won’t be a typedef, and the type of the block will appear directly in a method declaration. Here’s the Objective-C declaration for a UIView class method that takes two block parameters:

+ (void)animateWithDuration:(NSTimeInterval)duration

animations:(void (^)(void))animations

completion:(void (^)(BOOL finished))completion;

In that declaration, animations: is a block taking no parameters (void) and returning no value, and completion: is a block taking one parameter, a BOOL, and returning no value. Here’s the Swift translation:

class func animateWithDuration(duration: NSTimeInterval,

animations: () -> Void,

completion: ((Bool) -> Void)?)

(The completion: parameter’s type has been hand-tweaked as an Optional, to allow you to pass nil.)

Those are examples of methods that you would call, passing a function as argument where a block parameter is expected. Here’s an example of a method that you would implement, where a function is passed to you. This is the Objective-C declaration:

- (void)webView:(WKWebView *)webView

decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction

decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

You implement this method, and it is called when the user taps a link in a web view, so that you can decide how to respond. The third parameter is a block that takes one parameter — a WKNavigationActionPolicy, which is an enum — and returns no value. The block is passed to you as a Swift function, and you respond by calling the function to report your decision:

func webView(webView: WKWebView,

decidePolicyForNavigationAction navigationAction: WKNavigationAction,

decisionHandler: ((WKNavigationActionPolicy) -> Void)) {

// ...

decisionHandler(.Allow)

}

In Objective-C, a block can be cast to an id. A Swift function, however, cannot readily be cast to an AnyObject. Nevertheless, there are situations where, in Objective-C, you would have supplied a block where an id is expected, and you may wish to do the same thing in Swift, supplying a Swift function where an AnyObject is expected. For example, some object types, such as CALayer and CAAnimation, permit the use of key–value coding to attach an arbitrary key–value pair and to retrieve it later; it is perfectly reasonable to want to attach a function as the value.

A simple solution is to declare an NSObject subclass consisting of a single property of our function type:

typealias MyStringExpecter = (String) -> ()

class StringExpecterHolder : NSObject {

var f : MyStringExpecter! = nil

}

We can now wrap a function in an instance of our class:

func f (s:String) {println(s)}

let holder = StringExpecterHolder()

holder.f = f

We can then pass that instance where an AnyObject is expected:

let lay = CALayer()

lay.setValue(holder, forKey:"myFunction")

It is then a simple matter, at some future time, to extract the instance, cast it down from AnyObject, and call the function that it wraps:

let holder2 = lay.valueForKey("myFunction") as! StringExpecterHolder

holder2.f("testing")