iOS 8 Programming Fundamentals with Swift (2014)

Part III. Cocoa

The Cocoa Touch frameworks provide the general capabilities required by any iOS application. Buttons can be tapped, text can be read, screens of interface can succeed one another, because Cocoa makes it so. To use the framework, you must learn to let the framework use you. You must put your code in the right place so that it will be called at the right time. You must fulfill certain obligations that Cocoa expects of you. You master Cocoa by being Cocoa’s obedient servant. In this part of the book, that’s what you’ll learn to do.

§  Chapter 10 describes how Cocoa is organized and structured through such Objective-C language features as subclassing, categories, and protocols. Then some important built-in Cocoa object types are introduced. The chapter concludes with a description of Cocoa key–value coding and a look at how the root NSObject class is organized.

§  Chapter 11 presents Cocoa’s event-driven model of activity, along with its major design patterns and event-related features — notifications, delegation, data sources, target–action, the responder chain, and key–value observing. The chapter concludes with some words of wisdom about managing the barrage of events Cocoa will be throwing at you, and how to escape that barrage momentarily with delayed performance.

§  Chapter 12 is about Cocoa memory management. I’ll explain how memory management of reference types works. Then some special memory management situations are described: autorelease pools, retain cycles, notifications and timers, nib loading, and CFTypeRefs. The chapter concludes with a discussion of Cocoa property memory management, and advice on how to debug memory management issues.

§  Chapter 13 discusses the question of how your objects are going to see and communicate with one another within the confines of the Cocoa-based world. It concludes with some advice about adhering to the model–view–controller architecture.

Finally, don’t forget to read Appendix A for more detail about how Objective-C and Swift interact and cooperate.

Chapter 10. Cocoa Classes

When you program iOS, you’re programming Cocoa. So you need to be acquainted with Cocoa; you have to know, as it were, who you’re talking to when you talk to Cocoa, and what sort of behavior Cocoa is likely to expect from you. Cocoa is a big framework, subdivided into many smaller frameworks, and it takes time and experience to become reasonably familiar with it. (For full details, see my other book, Programming iOS 8.) Nevertheless, Cocoa has certain chief conventions and primary components that can serve as guideposts from the outset.

The Cocoa API is written mostly in Objective-C, and Cocoa itself consists mostly of Objective-C classes, derived from the root class, NSObject. When programming iOS, you’ll be using mostly the built-in Cocoa classes. Objective-C classes are comparable to and compatible with Swift classes, but the other two Swift object type flavors, structs and enums, are not matched by anything in Objective-C. Structs and enums declared originally in Swift cannot generally be handed across the bridge from Swift to Objective-C and Cocoa. Fortunately, some of the most important native Swift object types are also bridged to Cocoa classes. (See Appendix A for more details about the Objective-C language and how communications work between Swift and Objective-C.)

This chapter introduces Cocoa’s class structure. It discusses how Cocoa is conceptually organized, in terms of its underlying Objective-C features, and then surveys some of the most commonly encountered Cocoa utility classes, concluding with a discussion of the Cocoa root class and its features, which are inherited by all Cocoa classes.

Subclassing

Cocoa effectively hands you a large repertory of objects that already know how to behave in certain desirable ways. A UIButton, for example, knows how to draw itself and how to respond when the user taps it; a UITextField knows how to display editable text, how to summon the keyboard, and how to accept keyboard input.

Often, the default behavior or appearance of an object supplied by Cocoa won’t be quite what you’re after, and you’ll want to customize it. This does not necessarily mean that you need to subclass! Cocoa classes are heavily endowed with methods that you can call, and properties that you can set, precisely in order to customize an instance, and these will be your first resort. Always study the documentation for a Cocoa class to see whether instances can already be made to do what you want. For example, the class documentation for UIButton shows that you can set a button’s title, title color, internal image, background image, and many other features and behaviors, without subclassing.

Nevertheless, sometimes setting properties and calling methods won’t suffice to customize an instance the way you want to. In such cases, Cocoa may provide methods that are called internally as an instance does its thing, and whose behavior you can customize by subclassing and overriding (Chapter 4). You don’t have the source code for any of Cocoa’s built-in classes, but you can still subclass them, creating a new class that acts just like a built-in class except for the modifications you provide.

Certain Cocoa Touch classes are subclassed routinely. For example, a plain vanilla UIViewController, not subclassed, is very rare, and an iOS app without at least one UIViewController subclass would be practically impossible.

Another case in point is UIView. Cocoa Touch is full of built-in UIView subclasses that behave and draw themselves as needed (UIButton, UITextField, and so on), and you will rarely need to subclass any of them. On the other hand, you might create your own UIView subclass, whose job would be to draw itself in some completely new way. You don’t actually draw a UIView; rather, when a UIView needs drawing, its drawRect: method is called so that the view can draw itself. So the way to draw a UIView in some completely custom manner is to subclass UIView and implement drawRect: in the subclass. As the documentation says, “Subclasses that … draw their view’s content should override this method and implement their drawing code there.” The documentation is saying that you need to subclass UIView in order to draw content that is completely your own.

For example, suppose we want our window to contain a horizontal line. There is no horizontal line interface widget built into Cocoa, so we’ll just have to roll our own — a UIView that draws itself as a horizontal line. Let’s try it:

1.    In our Empty Window example project, choose File → New → File and specify iOS → Source → Cocoa Touch Class, and in particular a subclass of UIView. Call the class MyHorizLine. Xcode creates MyHorizLine.swift. Make sure it’s part of the app target.

2.    In MyHorizLine.swift, replace the contents of the class declaration with this (without further explanation):

3.  required init(coder aDecoder: NSCoder) {

4.      super.init(coder:aDecoder)

5.      self.backgroundColor = UIColor.clearColor()

6.  }

7.  override func drawRect(rect: CGRect) {

8.      let c = UIGraphicsGetCurrentContext()

9.      CGContextMoveToPoint(c, 0, 0)

10.    CGContextAddLineToPoint(c, self.bounds.size.width, 0)

11.    CGContextStrokePath(c)

}

12.Edit the storyboard. Find UIView in the Object library (it is called simply “View”), and drag it into the View object in the canvas. You may resize it to be less tall.

13.With the UIView that you just dragged into the canvas still selected, use the Identity inspector to change its class to MyHorizLine.

Build and run the app in the Simulator. You’ll see a horizontal line corresponding to the location of the top of the MyHorizLine instance in the nib. Our view has drawn itself as a horizontal line, because we subclassed it to do so.

In that example, we started with a bare UIView that had no drawing functionality of its own. That’s why there was no need to call super; the default implementation of UIView’s drawRect: does nothing. But you might also be able to subclass a built-in UIView subclass to modify the way it already draws itself. For example, the UILabel documentation shows that two methods are present for exactly this purpose. Both drawTextInRect: and textRectForBounds:limitedToNumberOfLines: explicitly tell us: “You should not call this method directly. This method should only be overridden by subclasses.” The implication is that these are methods that will be called for us, automatically, by Cocoa, as a label draws itself; thus, we can subclass UILabel and implement these methods in our subclass to modify how a particular type of label draws itself.

Here’s an example from one of my own apps, in which I subclass UILabel to make a label that draws its own rectangular border and has its content inset somewhat from that border, by overriding drawTextInRect:. As the documentation tells us: “In your overridden method, you can configure the current context further and then invoke super to do the actual drawing [of the text].” Let’s try it:

1.    In the Empty Window project, make a new class file, a UILabel subclass; call the class MyBoundedLabel.

2.    In MyBoundedLabel.swift, insert this code into the body of the class declaration:

3.  override func drawTextInRect(rect: CGRect) {

4.      let context = UIGraphicsGetCurrentContext()

5.      CGContextStrokeRect(context, CGRectInset(self.bounds, 1.0, 1.0))

6.      super.drawTextInRect(CGRectInset(rect, 5.0, 5.0))

}

7.    Edit the storyboard, add a UILabel to the interface, and change its class in the Identity inspector to MyBoundedLabel.

Build and run the app, and you’ll see how the rectangle is drawn and the label’s text is inset within it.

Oddly enough, however (and you might be particularly surprised by this if you’ve used another object-oriented application framework), subclassing is one of the rarer ways in which your code will relate to Cocoa. Knowing when to subclass can be somewhat tricky, but the general rule is that you probably shouldn’t subclass unless you’re explicitly invited to do so. Most built-in Cocoa Touch classes will never need subclassing (and some, in their documentation, downright forbid it).

One reason why subclassing is rare in Cocoa is that so many built-in classes use delegation (Chapter 11) as the preferred way of letting you customize their behavior. For example, you wouldn’t subclass UIApplication (the class of the singleton shared application instance) just in order to respond when the application has finished launching, because the delegate mechanism provides a way to do that (application:didFinishLaunchingWithOptions:). That’s why the templates give us an AppDelegate class, which is not a UIApplication subclass, but which does adopt the UIApplicationDelegate protocol.

On the other hand, if you needed to perform certain tricky customizations of your app’s fundamental event messaging behavior, you might subclass UIApplication in order to override sendEvent:. The documentation has a special “Subclassing Notes” section that tells you this, and also tells you, rightly, that doing so would be “very rare.” (See Chapter 6 on how to ensure that your UIApplication subclass is instantiated as the app launches.)

Categories and Extensions

category is an Objective-C language feature that allows code to reach right into an existing class and inject additional methods. This is comparable to a Swift extension (see Chapter 4). Using a Swift extension, you can add class or instance methods to a Cocoa class; the Swift headers make heavy use of extensions, both as a way of organizing Swift’s own object types and as a way of modifying Cocoa classes. In the same way, Cocoa uses categories to organize its own classes.

TIP

Objective-C categories have names, and you may see references to these names in the headers, the documentation, and so forth. However, the names are effectively meaningless, so don’t worry about them.

How Swift Uses Extensions

If you look in the main Swift header, you’ll see that many native object type declarations consist of an initial declaration followed by a series of extensions. For example, after declaring the generic struct Array<T>, the header proceeds to declare no fewer than eight extensions on the Array struct. Some of these add protocol adoptions; most of them don’t. All of them add declarations of properties or methods to Array; that’s what extensions are for.

These extensions are not, of themselves, functionally significant; the header could have declared the Array struct with all of those properties and methods within the body of a single declaration. Instead, it breaks things up into multiple extensions. The extensions are simply a way of clumping related functionality together, organizing this object type’s members so as to make them easier for human readers to understand.

In the Swift Core Graphics header, just about everything is an extension. Here Swift is adapting types defined elsewhere — adapting Swift numeric types for use with Core Graphics and the CGFloat numeric type, and adapting Cocoa structs such as CGPoint and CGRect as Swift object types. CGRect, in particular, is provided with numerous additional properties, initializers, and methods so that you can work with it directly as a Swift struct rather than having to call the Cocoa Core Graphics C utility functions that manipulate a CGRect.

How You Use Extensions

Swift permits you to write global functions, and there is nothing formally wrong with doing so. Nevertheless, for the sake of object-oriented encapsulation, you will often want to write a function as part of an existing object type. It will often be simplest and most sensible for you to inject such functions into an existing object type with an extension. Subclassing merely to add a method or two is heavy-handed — and besides, it often wouldn’t help you do what you need to do. (Besides, extensions work on all three flavors of Swift object type, whereas you can’t subclass a Swift enum or struct.)

For example, suppose you wanted to add a method to Cocoa’s UIView class. You could subclass UIView and declare your method, but then it would be present only in your UIView subclass and in subclasses of that subclass: it would not be present in UIButton, UILabel, and all the other built-in UIView subclasses — because they are subclasses of UIView, not of your subclass, and you can’t do anything to change that! An extension, on the other hand, solves the problem beautifully: you inject your method into UIView, and it is inherited by all built-in UIView subclasses as well.

Chapter 4 provides some examples of extensions I’ve written in my real iOS programming life (see Extensions). Also, as I explain there, I often use extensions in the same way as the Swift headers do, organizing my code for a single object type into multiple extensions simply for clarity.

How Cocoa Uses Categories

Cocoa uses categories as an organizational tool very much as Swift uses extensions. The declaration of a class will often be divided by functionality into multiple categories, and these will often appear in separate header files.

A good example is NSString. NSString is defined as part of the Foundation framework, and its basic methods are declared in NSString.h. Here we find that NSString itself, aside from its initializers, has just two methods, length and characterAtIndex:, because these are regarded as the minimum functionality that a string needs in order to be a string.

Additional NSString methods — those that create a string, deal with a string’s encoding, split a string, search in a string, and so on — are clumped into categories. These are shown in the Swift translation of the header as extensions. So, for example, after the declaration for the String class itself, we find this in the Swift translation of the header:

extension NSString {

    func getCharacters(

        buffer: UnsafeMutablePointer<unichar>, range aRange: NSRange)

    func substringFromIndex(from: Int) -> String

    // ...

}

That, as it turns out, is actually Swift’s translation of this Objective-C code:

@interface NSString (NSStringExtensionMethods)

- (void)getCharacters:(unichar *)buffer range:(NSRange)aRange;

- (NSString *)substringFromIndex:(NSUInteger)from;

// ...

@end

That notation — the keyword @interface, followed by a class name, followed by another name in parentheses — is an Objective-C category.

Moreover, although the declarations for some of Cocoa’s NSString categories appear in this same file, NSString.h, many of them appear elsewhere. For example:

§  A string may serve as a file pathname, so we also find a category on NSString in NSPathUtilities.h, where methods and properties such as pathComponents are declared for splitting a pathname string into its constituents and the like.

§  In NSURL.h, which is primarily devoted to declaring the NSURL class (and its categories), there’s also another NSString category, declaring methods for dealing with percent-escaping in a URL string, such as stringByAddingPercentEscapesUsingEncoding.

§  Off in a completely different framework (UIKit), NSStringDrawing.h adds two further NSString categories, with methods like drawAtPoint: having to do with drawing a string in a graphics context.

This organization won’t matter to you as a programmer, because an NSString is an NSString, no matter how it acquires its methods. But it can matter when you consult the documentation! The NSString methods declared in NSString.hNSPathUtilities.h, and NSURL.h are documented together in the NSString class documentation page. But the NSString methods declared in NSStringDrawing.h are not; instead, they appear in a separate document, NSString UIKit Additions Reference. (Presumably, this is because because they originate in a different framework.) As a result, the string drawing methods can be difficult to discover, especially as the NSString class documentation page doesn’t link to the other document. I regard this as a major flaw in the structure of the Cocoa documentation.

Protocols

Objective-C has protocols, and these are generally comparable to and compatible with Swift protocols (see Chapter 4). Since classes are the only Objective-C object type, all Objective-C protocols are seen by Swift as class protocols. Conversely, Swift protocols marked as @objc (which are implicitly class protocols) can be seen by Objective-C. Cocoa makes extensive use of protocols.

For example, let’s talk about how Cocoa objects are copied. Some objects can be copied; some can’t. This has nothing to do with an object’s class heritage. Yet we would like a uniform method to which any object that can be copied will respond. So Cocoa defines a protocol namedNSCopying, which declares just one requred method, copyWithZone:. Here’s how the NSCopying protocol is declared in Objective-C (in NSObject.h):

@protocol NSCopying

- (id)copyWithZone:(NSZone *)zone;

@end

That’s translated into Swift as follows:

protocol NSCopying {

    func copyWithZone(zone: NSZone) -> AnyObject

}

The NSCopying protocol declaration in NSObject.h, however, is not a statement that NSObject conforms to NSCopying. Indeed, NSObject does not conform to NSCopying! This doesn’t compile:

let obj = NSObject().copyWithZone(nil)

But this does compile, because NSString does conform to NSCopying (the literal "howdy" is implicitly bridged to NSString):

let s = "howdy".copyWithZone(nil)

A typical Cocoa pattern is that Cocoa wants to say: “An instance of any class will do here, provided it implements the following methods.” That, obviously, is a protocol. For example, consider how a protocol is used in connection with a table view (UITableView). A table view gets its data from a data source. For this purpose, UITableView declares a dataSource property, like this:

@property (nonatomic, assign) id<UITableViewDataSource> dataSource

That’s translated into Swift as follows:

unowned(unsafe) var dataSource: UITableViewDataSource?

(Ignore, for the moment, the memory management attributes of this property; I’ll talk about them in Chapter 12.) UITableViewDataSource is a protocol. The table view is saying: “I don’t care what class my data source belongs to, but whatever it is, it should conform to the UITableViewDataSource protocol.” Such conformance constitutes a promise that the data source will implement at least the required instance methods tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath:, which the table view will call when it needs to know what data to display. When you use a UITableView, and you want to provide it with a data source object, the class of that object will adopt UITableViewDataSource and will implement its required methods; otherwise, your code won’t compile:

let mc = MyClass()

let tv = UITableView()

tv.dataSource = mc // compile error: Type 'MyClass'...

// ...does not conform to protocol 'UITableViewDataSource'

Far and away the most pervasive use of protocols in Cocoa is in connection with the delegation pattern. I’ll discuss this pattern in detail in Chapter 11, but you can readily see an example in our handy Empty Window project: the AppDelegate class provided by the project template is declared like this:

class AppDelegate: UIResponder, UIApplicationDelegate { // ...

AppDelegate’s chief purpose on earth is to serve as the shared application’s delegate. The shared application object is a UIApplication, and UIApplication’s delegate property is declared like this:

unowned(unsafe) var delegate: UIApplicationDelegate?

The UIApplicationDelegate type is a protocol. This is how the shared UIApplication object knows that its delegate might be capable of receiving messages such as application:didFinishLaunchingWithOptions:. So the AppDelegate class officially announces its role by explicitly adopting the UIApplicationDelegate protocol.

A Cocoa protocol has its own documentation page. When the UIApplication class documentation tells you that the delegate property is typed as a UIApplicationDelegate, it’s implicitly telling you that if you want to know what messages a UIApplication’s delegate might receive, you need to look in the UIApplicationDelegate protocol documentation. You won’t find application:didFinishLaunchingWithOptions: mentioned anywhere on the UIApplication class documentation page! It’s documented in the UIApplicationDelegate protocol documentation page.

This separation of information can be particularly confusing when a class adopts a protocol. When a class’s documentation mentions that the class conforms to a protocol, don’t forget to examine that protocol’s documentation! The latter might contain important information about how the class behaves. To learn what messages can be sent to an object, you need to look upward through the superclass inheritance chain; you also need to look at any protocols that this object’s class (or superclass) conforms to. For example, as I already mentioned in Chapter 8, you won’t find out that UIViewController gets a viewWillTransitionToSize:withTransitionCoordinator: event by looking at the UIViewController class documentation page: you have to look in the documentation for the UIContentContainer protocol, which UIViewController adopts.

Informal Protocols

You may occasionally see, online or in the documentation, a reference to an informal protocol. An informal protocol isn’t really a protocol at all; it’s just a way of providing the compiler with a method signature so that it will allow a message to be sent without complaining.

There are two complementary ways to implement an informal protocol. One is to define a category on NSObject; this makes any object eligible to receive the messages listed in the category. The other is to define a protocol to which no class formally conforms; instead, messages listed in the protocol are sent only to objects typed as id (AnyObject), thus suppressing any possible objections from the compiler.

These techniques were widespread before protocols could declare methods as optional; now they are largely unnecessary, and are also mildly dangerous. In iOS 8, very few informal protocols remain — but they do exist. For example, NSKeyValueCoding (discussed later in this chapter) is an informal protocol; you may see the term NSKeyValueCoding in the documentation and elsewhere, but there isn’t actually any NSKeyValueCoding type: it’s a category on NSObject.

Optional Methods

Objective-C protocols, and Swift protocols marked as @objc, can have optional members (see Optional Protocol Members). The question thus arises: How, in practice, is an optional method feasible? We know that if a message is sent to an object and the object can’t handle that message, an exception is raised and your app will likely crash. But a method declaration is a contract suggesting that the object can handle that message. If we subvert that contract by declaring a method that might or might not be implemented, aren’t we inviting crashes?

The answer is that Objective-C is both dynamic and introspective. Objective-C can ask an object whether it can really deal with a message without actually sending it that message. The key method here is NSObject’s respondsToSelector: method, which takes a selector parameter and returns a Bool. (A selector is basically a method name expressed independently of any method call; see Appendix A.) Thus it is possible to send a message to an object only if it would be safe to do so.

Demonstrating respondsToSelector: in Swift is generally a little tricky, because it’s hard to get Swift to throw away its strict type checking long enough to let us send an object a message to which it might not respond. In this artificial example, I start by defining, at top level, two classes: one that derives from NSObject, because otherwise we can’t send respondsToSelector: to it, and another to declare the message that I want to send conditionally:

class MyClass : NSObject {

}

class MyOtherClass {

    @objc func woohoo() {}

}

Now I can say this:

let mc = MyClass()

if mc.respondsToSelector("woohoo") {

    (mc as AnyObject).woohoo()

}

Note the cast of mc to AnyObject. This causes Swift to abandon its strict type checking (see Suppressing type checking); we can now send this object any message that Swift knows about, provided it is susceptible to Objective-C introspection — that’s why I marked my woohoo declaration as@objc to start with. As you know, Swift provides a shorthand for sending a message conditionally — append a question mark to the name of the message:

let mc = MyClass()

(mc as AnyObject).woohoo?()

Behind the scenes, those two approaches are exactly the same; the latter is syntactic sugar for the former. In response to the question mark, Swift is calling respondsToSelector: for us, and will refrain from sending woohoo to this object if it doesn’t respond to this selector.

That explains also how optional protocol members work. It is no coincidence that Swift treats optional protocol members like AnyObject members. Here’s the example I gave in Chapter 4:

@objc protocol Flier {

    optional var song : String {get}

    optional func sing()

}

When you call sing?() on an object typed as a Flier, respondsToSelector: is called behind the scenes to determine whether this call is safe.

You wouldn’t want to send a message optionally, or call respondsToSelector: explicitly, before sending just any old message, because it isn’t generally necessary except with optional methods, and it slows things down a little. But Cocoa does in fact call respondsToSelector: on your objects as a matter of course. To see that this is true, implement respondsToSelector: on AppDelegate in our Empty Window project and instrument it with logging:

override func respondsToSelector(aSelector: Selector) -> Bool {

    println(aSelector)

    return super.respondsToSelector(aSelector)

}

The output on my machine, as the Empty Window app launches, includes the following (I’m omitting private methods and multiple calls to the same method):

application:handleOpenURL:

application:openURL:sourceApplication:annotation:

applicationDidReceiveMemoryWarning:

applicationWillTerminate:

applicationSignificantTimeChange:

application:willChangeStatusBarOrientation:duration:

application:didChangeStatusBarOrientation:

application:willChangeStatusBarFrame:

application:didChangeStatusBarFrame:

application:deviceAccelerated:

application:deviceChangedOrientation:

applicationDidBecomeActive:

applicationWillResignActive:

applicationDidEnterBackground:

applicationWillEnterForeground:

applicationWillSuspend:

application:didResumeWithOptions:

application:handleWatchKitExtensionRequest:reply:

application:shouldSaveApplicationState:

application:supportedInterfaceOrientationsForWindow:

application:performFetchWithCompletionHandler:

application:didReceiveRemoteNotification:fetchCompletionHandler:

application:willFinishLaunchingWithOptions:

application:didFinishLaunchingWithOptions:

That’s Cocoa, checking to see which of the optional UIApplicationDelegate protocol methods (including a couple of undocumented methods) are actually implemented by our AppDelegate instance — which, because it is the UIApplication object’s delegate and formally conforms to the UIApplicationDelegate protocol, has explicitly agreed that it might be willing to respond to any of those messages. The entire delegate pattern (Chapter 11) depends upon this technique. Observe the policy followed here by Cocoa: it checks all the optional protocol methods once, when it first meets the object in question, and presumably stores the results; thus, the app is slowed a tiny bit by this one-time initial bombardment of respondsToSelector: calls, but now Cocoa knows all the answers and won’t have to perform any of these same checks on the same object later.

Some Foundation Classes

The Foundation classes of Cocoa provide basic data types and utilities that will form the basis of your communication with Cocoa. Obviously I can’t list all of them, let alone describe them fully, but I can survey those that you’ll probably want to be aware of before writing even the simplest iOS program. For more information, start with Apple’s list of the Foundation classes in the Foundation Framework Reference.

Useful Structs and Constants

NSRange is a C struct (see Appendix A) of importance in dealing with some of the classes I’m about to discuss. Its components are integers, location and length. For example, an NSRange whose location is 1 starts at the second element of something (because element counting is always zero-based), and if its length is 2 it designates this element and the next.

Cocoa supplies various convenience functions for dealing with an NSRange; for example, you can create an NSRange from two integers by calling NSMakeRange. (Note that the name, NSMakeRange, is backward compared to names like CGPointMake and CGRectMake.) Swift helps out by bridging NSRange as a Swift struct. Moreover, you can coerce between an NSRange and a Swift Range whose endpoints are Ints: Swift gives NSRange an initializer that takes a Swift Range, along with a toRange method.

NSNotFound is a constant integer indicating that some requested element was not found. The true numeric value of NSNotFound is of no concern to you; always compare against NSNotFound itself, to learn whether a result is meaningful. For example, if you ask for the index of a certain object in an NSArray and the object isn’t present, the result is NSNotFound:

let arr = ["hey"] as NSArray

let ix = arr.indexOfObject("ho")

if ix == NSNotFound {

    println("it wasn't found")

}

Why does Cocoa resort to an integer value with a special meaning in this way? Because it has to. The result could not be 0 to indicate the absence of the object, because 0 would indicate the first element of the array. Nor could it be -1, because an NSArray index value is always positive. Nor could it be nil, because Objective-C can’t return nil when an integer is expected (and even if it could, it would be seen as another way of saying 0). Contrast Swift, whose find global method returns an Int wrapped in an Optional, allowing it to return nil to indicate that the target object wasn’t found.

If a search returns a range and the thing sought is not present, the location component of the resulting NSRange will be NSNotFound. As I mentioned in Chapter 3, Swift will sometimes do some clever automatic bridging for you, thus saving you the trouble of comparing withNSNotFound. The canonical example is NSString’s rangeOfString: method. As defined in Cocoa, it returns an NSRange; Swift reconfigures it to return a Swift Range (of String.Index) wrapped in an Optional, returning nil if the NSRange’s location is NSNotFound:

let s = "howdy"

let r = s.rangeOfString("ha") // nil; an Optional wrapping a Swift Range

That’s great if what you wanted is a Swift Range, suitable for further slicing a Swift String; but if you wanted an NSRange, suitable for handing back to Cocoa, you’ll need to cast your original Swift String to an NSString to start with — thus causing the result to remain in the Cocoa world:

let s = "howdy" as NSString

let r = s.rangeOfString("ha") // an NSRange

if r.location == NSNotFound {

    println("it wasn't found")

}

NSString and Friends

NSString is the Cocoa object version of a string. NSString and Swift String are bridged to one another, and you will often move between them without thinking, passing a Swift String to Cocoa where an NSString is expected, calling Cocoa NSString methods on a Swift String, and so forth. For example:

let s = "hello"

let s2 = s.capitalizedString

In that code, s is a Swift String and s2 is a Swift String, but the capitalizedString property actually belongs to Cocoa. In the course of that code, a Swift String has been bridged to NSString and passed to Cocoa, which has processed it to get the capitalized string; the capitalized string is an NSString, but it has been bridged back to a Swift String. In all likelihood, you are not conscious of the bridging; capitalizedString feels like a native String property, but it isn’t — as you can readily prove by trying to use it in an environment where Foundation is not imported (you can’t do it).

In some cases, you will need to cross the bridge yourself by casting explicitly. The problem typically arises where you need to provide an index on a string. For example:

let s = "hello"

let s2 = s.substringToIndex(4) // compile error

The problem here is that the bridging is in your way. Swift has no objection to your calling the substringToIndex: method on a Swift String, but then the index value must be a String.Index, which is rather tricky to construct (see Chapter 3):

let s2 = s.substringToIndex(advance(s.startIndex,4))

If you don’t want to talk that way, you must cast the String to an NSString beforehand; now you are in Cocoa’s world, where string indexes are integers:

let s2 = (s as NSString).substringToIndex(4)

As I explained in Chapter 3, however, those two calls are not equivalent: they can give different answers! The reason is that String and NSString have fundamentally different notions of what constitutes an element of a string (see The String–NSString Element Mismatch). A String is a Swift sequence, and must resolve its elements into characters, which means that it must walk the string, coalescing any combining codepoints; an NSString behaves as if it were an array of UTF16 codepoints. On the Swift side, each increment in a String.Index corresponds to a true character, but access by index or range requires walking the string; on the Cocoa side, access by index or range is extremely fast, but might not correspond to character boundaries. (See the “Characters and Grapheme Clusters” chapter of Apple’s String Programming Guide.)

Another important difference between a Swift String and a Cocoa NSString is that an NSString is immutable. This means that, with NSString, you can do things such as obtain a new string based on the first — as capitalizedString and substringToIndex: do — but you can’t change the string in place. To do that, you need another class, a subclass of NSString, NSMutableString. NSMutableString has many useful methods, and you’ll probably want to take advantage of them; but Swift String isn’t bridged to NSMutableString, so you can’t get from String to NSMutableString merely by casting. To obtain an NSMutableString, you’ll have to make one. The simplest way is with NSMutableString’s initializer init(string:), which expects an NSString — meaning that you can pass a Swift String. Coming back the other way, you can cast all the way from NSMutableString a Swift String in one move:

let s = "hello"

let ms = NSMutableString(string:s)

ms.deleteCharactersInRange(NSMakeRange(ms.length-1,1))

let s2 = (ms as String) + "ion" // now s2 is a Swift String

As I said in Chapter 3, native Swift String methods are thin on the ground. All the real string-processing power lives over on the Cocoa side of the bridge. So you’re going to be crossing that bridge a lot! And this will not be only for the power of the NSString and NSMutableString classes. Many other useful classes are associated with them.

For example, suppose you want to search a string for some substring. All the best ways come from Cocoa:

§  An NSString can be searched using various rangeOfString:... methods, with numerous options such as ignoring diacriticals, ignoring case, starting at the end, and insisting that the substring occupy the start or end of the searched string.

§  Perhaps you don’t know exactly what you’re looking for: you need to describe it structurally. NSScanner lets you walk through a string looking for pieces that fit certain criteria; for example, with NSScanner (and NSCharacterSet) you can skip past everything in a string that precedes a number and then extract the number.

§  By specifying the option .RegularExpressionSearch, you can search using a regular expression. Regular expressions are also supported as a separate class, NSRegularExpression, which in turn uses NSTextCheckingResult to describe match results.

§  More sophisticated automated textual analysis is supported by some additional classes, such as NSDataDetector, an NSRegularExpression subclass that efficiently finds certain types of string expression such as a URL or a phone number, and NSLinguisticTagger, which actually attempts to analyze text into its grammatical parts of speech.

In this example, our goal is to replace all occurrences of the word “hell” with the word “heaven.” We don’t want to replace mere occurrences of the substring “hell” — for example, “hello” should be left intact. Thus our search needs some intelligence as to what constitutes a word boundary. That sounds like a job for a regular expression. Swift doesn’t have regular expressions, so everything has to be done by Cocoa:

var s = NSMutableString(string:"hello world, go to hell")

let r = NSRegularExpression(

    pattern: "\\bhell\\b",

    options: .CaseInsensitive, error: nil)!

r.replaceMatchesInString(

    s, options: nil, range: NSMakeRange(0,s.length),

    withTemplate: "heaven")

NSString also has convenience utilities for working with a file path string, and is often used in conjunction with NSURL, which is another Foundation class worth looking into. In addition, NSString — like some other classes discussed in this section — provides methods for writing out to a file’s contents or reading in a file’s contents; the file can be specified either as an NSString file path or as an NSURL.

An NSString carries no font and size information. Interface objects that display strings (such as UILabel) have a font property that is a UIFont; but this determines the single font and size in which the string will display. If you want styled text — where different runs of text have different style attributes (size, font, color, and so forth) — you need to use NSAttributedString, along with its supporting classes NSMutableAttributedString, NSParagraphStyle, and NSMutableParagraphStyle. These allow you to style text and paragraphs easily in sophisticated ways. The built-in interface objects that display text can display an NSAttributedString.

String drawing in a graphics context can be performed with methods provided through the NSStringDrawing category on NSString (see the String UIKit Additions Reference) and on NSAttributedString (see the NSAttributedString UIKit Additions Reference).

NSDate and Friends

An NSDate is a date and time, represented internally as a number of seconds (NSTimeInterval) since some reference date. Calling NSDate’s initializer init() — i.e., saying NSDate() — gives you a date object for the current date and time. Date operations involving anything simpler than a count of seconds will involve the use of NSDateComponents, and conversions between NSDate and NSDateComponents require that you pass through an NSCalendar. Here’s an example of constructing a date based on its calendrical values:

let greg = NSCalendar(calendarIdentifier:NSGregorianCalendar)!

let comp = NSDateComponents()

comp.year = 2015

comp.month = 8

comp.day = 10

comp.hour = 15

let d = greg.dateFromComponents(comp) // Optional wrapping NSDate

Similarly, NSDateComponents provides the correct way to do date arithmetic. Here’s how to add one month to a given date:

let d = NSDate() // or whatever

let comp = NSDateComponents()

comp.month = 1

let greg = NSCalendar(calendarIdentifier:NSGregorianCalendar)!

let d2 = greg.dateByAddingComponents(comp, toDate:d, options:nil)

You will also likely be concerned with dates represented as strings. If you don’t take explicit charge of a date’s string representation, it is represented by a string whose format may surprise you. For example, if you simply println an NSDate, you are shown the date in the GMT timezone, which can be confusing if that isn’t where you live. A simple solution is to call descriptionWithLocale:; the locale comprises the user’s current time zone, language, region format, and calendar settings:

println(d)

// 2015-02-02 16:36:41 +0000

println(d.descriptionWithLocale(NSLocale.currentLocale()))

// Optional("Monday, February 2, 2015 at 8:36:41 AM Pacific Standard Time")

For exact creation and parsing of date strings, use NSDateFormatter, which uses a format string similar to NSLog (and NSString’s stringWithFormat:). In this example, we surrender completely to the user’s locale by generating an NSDateFormatter’s format withdateFormatFromTemplate:options:locale: and the current locale. The “template” is a string listing the date components to be used, but their order, punctuation, and language are left up to the locale:

let df = NSDateFormatter()

let format = NSDateFormatter.dateFormatFromTemplate(

    "dMMMMyyyyhmmaz", options:0, locale:NSLocale.currentLocale())

df.dateFormat = format

let s = df.stringFromDate(NSDate()) // just now

The result is the date shown in the user’s time zone and language, using the correct linguistic conventions. It involves a combination of region format and language, which are two separate settings. Thus:

§  On my device, the result might be “February 2, 2015, 8:36 AM PST.”

§  If I change my device’s region to France, it might be “2 February 2015 8:36 am GMT-8.”

§  If I also change my device’s language to French, it might be “2 février 2015 8:36 AM UTC−8.”

NSNumber

An NSNumber is an object that wraps a numeric value. The wrapped value can be any standard Objective-C numeric type (including BOOL, the Objective-C equivalent of Swift Bool). It comes as a surprise to Swift users that NSNumber is needed. But an ordinary number in Objective-C is not an object (it is a scalar; see Appendix A), so it cannot be used where an object is expected. Thus, NSNumber solves an important problem, converting a number into an object and back again.

Swift does its best to shield you from having to deal directly with NSNumber. It bridges Swift numeric types to Objective-C in two different ways:

§  If an ordinary number is expected, a Swift number is bridged to an ordinary number (a scalar).

§  If an object is expected, a Swift number is bridged to an NSNumber.

Here’s an example:

let ud = NSUserDefaults.standardUserDefaults()

ud.setInteger(0, forKey: "Score") 1

ud.setObject(0, forKey: "Score") 2

The second and third lines look alike, but Swift treats the literal 0 differently:

1

In the second line, setInteger:forKey: expects an integer (a scalar) as its first parameter, so Swift turns the Int struct value 0 into an ordinary Objective-C number.

2

In the third line, setObject:forKey: expects an object as its first parameter, so Swift turns the Int struct value 0 into an NSNumber.

Naturally, if you need to cross the bridge explicitly, you can. You can cast a Swift number to an NSNumber:

let n = 0 as NSNumber

For more control over what numeric type an NSNumber will wrap, you can call one of NSNumber’s initializers:

let n = NSNumber(float:0)

Coming back from Objective-C to Swift, a value will typically arrive as an AnyObject and you will have to cast down. NSNumber comes with properties for accessing the wrapped value by its numeric type. Recall this example from Chapter 5, involving an NSNumber extracted as a value from an NSNotification’s userInfo dictionary:

if let ui = n.userInfo {

    if let prog = ui["progress"] as? NSNumber {

        self.progress = prog.doubleValue

    }

}

If an AnyObject is actually an NSNumber, you can cast all the way down to a Swift numeric type. Thus, the same example can be rewritten like this, without explicitly mentioning NSNumber:

if let ui = n.userInfo {

    if let prog = ui["progress"] as? Double {

        self.progress = prog

    }

}

In the second version, Swift is actually doing behind the scenes exactly what we did in the first version — treating an AnyObject as an NSNumber and getting its doubleValue property to extract the wrapped number.

An NSNumber object is just a wrapper and no more. It can’t be used directly for numeric calculations; it isn’t a number. It wraps a number. One way or another, if you want a number, you have to extract it from the NSNumber.

An NSNumber subclass, NSDecimalNumber, on the other hand, can be used in calculations, thanks to a bunch of arithmetic methods:

let dec1 = NSDecimalNumber(float: 4.0)

let dec2 = NSDecimalNumber(float: 5.0)

let sum = dec1.decimalNumberByAdding(dec2) // 9.0

NSDecimalNumber is useful particularly for rounding, because there’s a handy way to specify the desired rounding behavior.

Underlying NSDecimalNumber is the NSDecimal struct (it is an NSDecimalNumber’s decimalValue). NSDecimal comes with C functions that are faster than NSDecimalNumber methods.

NSValue

NSValue is NSNumber’s superclass. It is used for wrapping nonnumeric C values, such as C structs, where an object is expected. The problem being solved here is parallel to the problem solved by NSNumber: a Swift struct is an object, but a C struct is not, so a struct cannot be used in Objective-C where an object is expected.

Convenience methods provided through the NSValueUIGeometryExtensions category on NSValue (see the NSValue UIKit Additions Reference) allow easy wrapping and unwrapping of CGPoint, CGSize, CGRect, CGAffineTransform, UIEdgeInsets, and UIOffset; additional categories allow easy wrapping and unwrapping of NSRange, CATransform3D, CMTime, CMTimeMapping, CMTimeRange, MKCoordinate, and MKCoordinateSpan. You are unlikely to need to store any other kind of C value in an NSValue, but you can if you need to.

Swift will not magically bridge any of these C struct types to or from an NSValue. You must manage them explicitly, exactly as you would do if your code were written in Objective-C. In this example from my own code, we use Core Animation to animate the movement of a button in the interface from one position to another; the button’s starting and ending positions are each expressed as a CGPoint, but an animation’s fromValue and toValue must be objects. A CGPoint is not an Objective-C object, so we must wrap the CGPoint values in NSValue objects:

let ba = CABasicAnimation(keyPath:"position")

ba.duration = 10

ba.fromValue = NSValue(CGPoint:self.oldButtonCenter)

ba.toValue = NSValue(CGPoint:goal)

self.button.layer.addAnimation(ba, forKey:nil)

Similarly, you can make an array of CGPoint in Swift, because CGPoint becomes a Swift object type (a Swift struct), and a Swift Array can have elements of any type; but you can’t hand such an array to Objective-C, because an Objective-C NSArray must have objects as its elements, and a CGPoint, in Objective-C, is not an object. Thus you must wrap the CGPoints in NSValue objects first. This is another animation example, where I set the values array (an NSArray) of a keyframe animation by turning an array of CGPoints into an array of NSValues:

anim.values = [oldP,p1,p2,newP].map{NSValue(CGPoint:$0)}

NSData

NSData is a general sequence of bytes; basically, it’s just a buffer, a chunk of memory. It is immutable; the mutable version is its subclass NSMutableData.

In practice, NSData tends to arise in two main ways:

§  When downloading data from the Internet. For example, NSURLConnection and NSURLSession supply whatever they retrieve from the Internet as NSData. Transforming it from there into (let’s say) a string, specifying the correct encoding, would then be up to you.

§  When storing an object as a file or in user preferences. For example, you can’t store a UIColor value directly into user preferences. So if the user has made a color choice and you need to save it, you transform the UIColor into an NSData (using NSKeyedArchiver) and save that:

§  let ud = NSUserDefaults.standardUserDefaults()

§  let c = UIColor.blueColor()

§  let cdata = NSKeyedArchiver.archivedDataWithRootObject(c)

ud.setObject(cdata, forKey: "myColor")

Equality and Comparison

In Swift, the equality and comparison operators can be overridden for an object type that adopts Equatable and Comparable (Operators). But Objective-C operators can’t do that; they are applicable only to scalars.

To permit determination of whether two objects are “equal” — whatever that may mean for this object type — an Objective-C class must implement isEqual:, which is inherited from NSObject. Swift will help out by treating NSObject as Equatable and by permitting the use of the ==operator, implicitly converting it to an isEqual: call. Thus, if a class does implement isEqual:, ordinary Swift comparison will work. For example:

let n1 = NSNumber(integer:1)

let n2 = NSNumber(integer:2)

let n3 = NSNumber(integer:3)

let ok = n2 == 2 // true 1

let ok2 = n2 == NSNumber(integer:2) // true 2

let ix = find([n1,n2,n3], 2) // Optional wrapping 1 3

That code seems to do three impossible things before breakfast:

1

We directly compare an Int to an NSNumber, and we get the right answer, as if we were comparing the Int to the integer wrapped by that NSNumber.

2

We directly compare two NSNumber objects to one another, and we get the right answer, as if we were comparing the integers that they wrap.

3

We treat an array of NSNumber objects as an array of Equatables and pass it to the find function, and we successfully determine which NSNumber object is “equal” to an actual number.

There are two parts to this apparent magic:

§  The numbers are being wrapped in NSNumber objects for us.

§  The == operator (also used behind the scenes by the find function) is being converted to an isEqual: call.

NSNumber implements isEqual: to compare two NSNumber objects by comparing the numeric values that they wrap; therefore the equality comparisons all work correctly.

If an NSObject subclass doesn’t implement isEqual:, it inherits NSObject’s implementation, which compares the two objects for identity (like Swift’s === operator). For example, these two Dog objects can be compared with the == operator, even though Dog does not adopt Equatable, because they derive from NSObject — but Dog doesn’t implement isEqual:, so == defaults to NSObject’s identity comparison:

class Dog : NSObject {

    var name : String

    init(_ name:String) {self.name = name}

}

let d1 = Dog("Fido")

let d2 = Dog("Fido")

let ok = d1 == d2 // false

A number of classes that implement isEqual: also implement more specific and efficient tests. The usual Objective-C way to determine whether two NSNumber objects are equal (in the sense of wrapping identical numbers) is by calling isEqualToNumber:. Similarly, NSString hasisEqualToString:, NSDate has isEqualToDate:, and so forth. However, these classes do also implement isEqual:, so I don’t think there’s any reason not to use the Swift == operator.

Similarly, in Objective-C it is up to individual classes to supply ordered comparison methods. The standard method is called compare:, and returns one of three NSComparisonResult cases:

.OrderedAscending

The receiver is less than the argument.

.OrderedSame

The receiver is equal to the argument.

.OrderedDescending

The receiver is greater than the argument.

Swift comparison operators (< and so forth) do not magically call compare: for you. You can’t compare two NSNumber values directly:

let n1 = NSNumber(integer:1)

let n2 = NSNumber(integer:2)

let ok = n1 < n2 // compile error

You will typically fall back on calling compare: yourself, exactly as in Objective-C:

let n1 = NSNumber(integer:1)

let n2 = NSNumber(integer:2)

let ok = n1.compare(n2) == .OrderedAscending // true

NSIndexSet

NSIndexSet represents a collection of unique whole numbers; its purpose is to express element numbers of an ordered collection, such as an NSArray. Thus, for instance, to retrieve multiple objects simultaneously from an array, you specify the desired indexes as an NSIndexSet. It is also used with other things that are array-like; for example, you pass an NSIndexSet to a UITableView to indicate what sections to insert or delete.

To take a specific example, let’s say you want to speak of elements 1, 2, 3, 4, 8, 9, and 10 of an NSArray. NSIndexSet expresses this notion in some compact implementation that can be readily queried. The actual implementation is opaque, but you can imagine that this NSIndexSet might consist of two NSRange structs, {1,4} and {8,3}, and NSIndexSet’s methods actually invite you to think of an NSIndexSet as composed of ranges.

An NSIndexSet is immutable; its mutable subclass is NSMutableIndexSet. You can form a simple NSIndexSet consisting of just one contiguous range directly, by passing an NSRange to indexSetWithIndexesInRange:; but to form a more complex index set you’ll need to use NSMutableIndexSet so that you can append additional ranges:

var arr = ["zero", "one", "two", "three", "four", "five"]

arr.extend(["six", "seven", "eight", "nine", "ten"])

let ixs = NSMutableIndexSet()

ixs.addIndexesInRange(NSRange(1...4))

ixs.addIndexesInRange(NSRange(8...10))

let arr2 = (arr as NSArray).objectsAtIndexes(ixs)

To walk through (enumerate) the index values specified by an NSIndexSet, you can use for...in; alternatively, you can walk through an NSIndexSet’s indexes or ranges by calling enumerateIndexesUsingBlock: or enumerateRangesUsingBlock: or their variants.

NSArray and NSMutableArray

NSArray is Objective-C’s array object type. It is fundamentally similar to Swift Array, and they are bridged to one another; but when crossing the bridge, certain restrictions must be obeyed:

§  NSArray elements must be Objective-C objects. That means, in effect, that they must be class instances, or instances of Swift types that are bridged to Objective-C class types.

§  NSArray has no information as to the type of its elements. Unlike Swift, different elements can be of different types. Therefore, any NSArray arriving from Objective-C into Swift is typed as [AnyObject].

For a full discussion of how to bridge back and forth between Swift Array and Objective-C NSArray, implicitly and by casting, see Swift Array and Objective-C NSArray.

An NSArray’s length is its count, and a particular object can be obtained by index number using objectAtIndex:. The index of the first object, as with a Swift Array, is zero, so the index of the last object is count minus one.

Instead of calling objectAtIndex:, you can use subscripting with an NSArray. This is not because NSArray is bridged to Swift Array, but because NSArray implements objectAtIndexedSubscript:. This method is the Objective-C equivalent of a Swift subscript getter, and Swift knows this. In fact, by a kind of trickery, when you examine the NSArray header file translated into Swift, this method is shown as a subscript declaration! Thus, the Objective-C version of the header file shows this declaration:

- (id)objectAtIndexedSubscript:(NSUInteger)idx;

But the Swift version of the same header file shows this:

subscript (idx: Int) -> AnyObject { get }

You can seek an object within an array with indexOfObject: or indexOfObjectIdenticalTo:; the former’s idea of equality is to call isEqual:, whereas the latter uses object identity (like Swift’s ===). As I mentioned earlier, if the object is not found in the array, the result isNSNotFound.

Unlike a Swift Array, and like an Objective-C NSString, an NSArray is immutable. This doesn’t mean you can’t mutate any of the objects it contains; it means that once the NSArray is formed you can’t remove an object from it, insert an object into it, or replace an object at a given index. To do those things while staying in the Objective-C world, you can derive a new array consisting of the original array plus or minus some objects, or use NSArray’s subclass, NSMutableArray. Swift Array is not bridged to NSMutableArray; if you want an NSMutableArray, you must create it. The simplest way is with the NSMutableArray initializers, init() or init(array:).

Once you have an NSMutableArray, you can call methods such as NSMutableArray’s addObject: and replaceObjectAtIndex:withObject:. You can also assign into an NSMutableArray using subscripting. Again, this is because NSMutableArray implements a special method,setObject:atIndexedSubscript:; Swift recognizes this as equivalent to a subscript setter.

Coming back the other way, you cannot cast directly from NSMutableArray to a Swift Array of any type other than [AnyObject]; the usual approach is to cast up from NSMutableArray to NSArray and then down to a specific type of Swift Array:

let marr = NSMutableArray()

marr.addObject(1) // an NSNumber

marr.addObject(2) // an NSNumber

let arr = marr as NSArray as! [Int]

Cocoa provides ways to search or filter an array using a block. You can also derive a sorted version of an array, supplying the sorting rules in various ways, or if it’s a mutable array, you can sort it directly. You might prefer to perform those kinds of operation in the Swift Array world, but it can be useful to know how to do them the Cocoa way. For example:

let pep = ["Manny", "Moe", "Jack"] as NSArray

let ems = pep.objectsAtIndexes(

    pep.indexesOfObjectsPassingTest {

        obj, idx, stop in

        return (obj as! NSString).rangeOfString(

                "m", options:.CaseInsensitiveSearch

            ).location == 0

    }

) // ["Manny", "Moe"]

NSDictionary and NSMutableDictionary

NSDictionary is Objective-C’s dictionary object type. It is fundamentally similar to Swift Dictionary, and they are bridged to one another; but when crossing the bridge, certain restrictions must be obeyed:

§  NSDictionary keys will usually be an NSString, but they don’t have to be; the formal requirement is that they be Objective-C objects whose classes adopt NSCopying. NSDictionary uses hashing under the hood, but it does not formally require hashability, because NSObject itself is hashable. Therefore, the Swift equivalent is to see NSDictionary keys as a form of NSObject, which Swift extends to adopt Hashable.

§  NSDictionary values must be Objective-C objects.

§  NSDictionary has no information as to the type of its keys and values. Unlike Swift, different keys can be of different types, and different values can be of different types. Therefore, any NSDictionary arriving from Objective-C into Swift is typed as [NSObject:AnyObject].

See Swift Dictionary and Objective-C NSDictionary for a full discussion of how to bridge back and forth between Swift Dictionary and Objective-C NSDictionary, including casting.

An NSDictionary is immutable; its mutable subclass is NSMutableDictionary. Swift Dictionary is not bridged to NSMutableDictionary; you can most easily make an NSMutableDictionary with an initializer, init() or init(dictionary:).

The keys of an NSDictionary are distinct (using isEqual: for comparison). If you add a key–value pair to an NSMutableDictionary, then if that key is not already present, the pair is simply added, but if the key is already present, then the corresponding value is replaced. This is parallel to the behavior of Swift Dictionary.

The fundamental use of an NSDictionary is to request an entry’s value by key (using objectForKey:); if no such key exists, the result is nil. In Objective-C, nil is not an object, and thus cannot be a value in an NSDictionary; the meaning of this response is thus unambiguous. Swift handles this by treating the result of objectForKey: as an AnyObject? — that is, an Optional wrapping an AnyObject.

Subscripting is possible on an NSDictionary or an NSMutableDictionary for similar reasons to why subscripting is possible on an NSArray or an NSMutableArray. NSDictionary implements objectForKeyedSubscript:, and Swift understands this as equivalent to a subscript getter. In addition, NSMutableDictionary implements setObject:forKeyedSubscript:, and Swift understands this as equivalent to a subscript setter.

You can get from an NSDictionary a list of keys (allKeys), a list of values (allValues), or a list of keys sorted by value. You can also walk through the key–value pairs together using a block, and you can even filter an NSDictionary by a test against its values.

NSSet and Friends

An NSSet is an unordered collection of distinct objects. “Distinct” means that no two objects in a set can return true when they are compared using isEqual:. Learning whether an object is present in a set is much more efficient than seeking it in an array, and you can ask whether one set is a subset of, or intersects, another set. You can walk through (enumerate) a set with the for...in construct, though the order is of course undefined. You can filter a set, as you can an NSArray. Indeed, much of what you can do with a set is parallel to what you can do with an array, except that of course you can’t do anything with a set that involves the notion of ordering.

To escape even that restriction, you can use an ordered set. An ordered set (NSOrderedSet) is very like an array, and the methods for working with it are very similar to the methods for working with an array — you can even fetch an element by subscripting (because it implementsobjectAtIndexedSubscript:). But an ordered set’s elements must be distinct. An ordered set provides many of the advantages of sets: for example, as with an NSSet, learning whether an object is present in an ordered set is much more efficient than for an array, and you can readily take the union, intersection, or difference with another set. Since the distinctness restriction will often prove no restriction at all (because the elements were going to be distinct anyway), it is worthwhile to use NSOrderedSet instead of NSArray wherever possible.

TIP

Handing an array over to an ordered set uniques the array, meaning that order is maintained but only the first occurrence of an equal object is moved to the set.

An NSSet is immutable. You can derive one NSSet from another by adding or removing elements, or you can use its subclass, NSMutableSet. Similarly, NSOrderedSet has its mutable counterpart, NSMutableOrderedSet (which you can insert into by subscripting, because it implementssetObject:atIndexedSubscript:). There is no penalty for adding to, or inserting into, a mutable set an object that the set already contains; nothing is added (and so the distinctness rule is enforced), but there’s no error.

NSCountedSet, a subclass of NSMutableSet, is a mutable unordered collection of objects that are not necessarily distinct (this concept is often referred to as a bag). It is implemented as a set plus a count of how many times each element has been added.

In Swift 1.2, Set is bridged to NSSet, with restrictions similar to NSArray. Nothing in Swift is bridged to NSMutableSet, NSCountedSet, NSOrderedSet, or NSMutableOrderedSet, but they are easily formed by coercion from a set or an array using an initializer. Coming back the other way, Swift receives an NSSet as a Set<AnyObject>; you can cast an NSSet down to a specific type of Swift Set, and thus you can cast an NSMutableSet or NSCountedSet up to NSSet and down to a Swift Set (similar to an NSMutableArray). NSOrderedSet comes with “façade” properties that present it as an array or a set. Because of their special behaviors, however, you are much more likely to leave an NSCountedSet or an NSOrderedSet in its Objective-C form for as long you’re working with it.

NSNull

The NSNull class does nothing but supply a pointer to a singleton object, NSNull(). This singleton object is used to stand for nil in situations where an actual Objective-C object is required and nil is not permitted. For example, you can’t use nil as the value of an element of a collection (such as NSArray, NSSet, or NSDictionary), and Objective-C knows nothing about Swift Optionals, so you’d use NSNull() instead.

You can test an object for equality against NSNull() using the ordinary equality operator (==), because it falls back on NSObject’s isEqual:, which is identity comparison. This is a singleton instance, and therefore identity comparison works.

Immutable and Mutable

Beginners sometimes have difficulty with the Cocoa Foundation notion of class pairs where the superclass is immutable and the subclass is mutable. This notion is itself reminiscent of the Swift distinction between a constant (let) and a true variable (var), and has similar consequences. For example, the fact that NSArray is “immutable” means much the same thing as the fact that a Swift Array is referred to with let: you can’t append or insert into this array, or replace or delete an element of this array, but if its elements are reference types — and of course, for an NSArray, theyare reference types — you can mutate an element in place. Nevertheless, from Swift’s point of view, these are all class instances, and so they are equally mutable through properties and methods even if a reference is declared with let. Immutability here is purely internal to the class implementation.

The reason why Cocoa needs these immutable/mutable pairs is to prevent unauthorized mutation. These are ordinary classes, so an NSArray object, say, is an ordinary class instance — a reference type. If a class has an NSArray property, and if this array were mutable, the array could be mutated by some other object, behind this class’s back. To prevent that from happening, a class will work internally and temporarily with a mutable instance but then store and vend to other classes an immutable instance, thus protecting the value from being changed accidentally or behind its own back. (Swift doesn’t face the same issue, because its fundamental built-in object types such as String, Array, and Dictionary are structs, and therefore are value types, which cannot be mutated in place; they can be changed only by being replaced, and that is something that can be guarded against or detected through a setter observer.)

The documentation may not make it completely obvious that the mutable classes obey and, if appropriate, override the methods of their immutable superclasses. For example, dozens of NSMutableArray methods are not listed on NSMutableArray’s class documentation page, because they are inherited from NSArray. And when such methods are inherited by the mutable subclass, they may be overridden to fit the mutable subclass. For example, NSArray’s init(array:) generates an immutable array, but NSMutableArray’s init(array:) — which isn’t even listed on the NSMutableArray documentation page, because it is inherited from NSArray — generates a mutable array.

That fact also answers the question of how to make an immutable array mutable, and vice versa. If init(array:), sent to the NSArray class, yields a new immutable array containing the same objects in the same order as the original array, then the same initializer, init(array:), sent to the NSMutableArray class, yields a mutable array containing the same objects in the same order as the original. Thus this single method can transform an array between immutable and mutable in either direction. You can also use copy (produces an immutable copy) and mutableCopy(produces a mutable copy), both inherited from NSObject; but these are not as convenient because they yield an AnyObject which must then be cast.

WARNING

These immutable/mutable class pairs are all implemented as class clusters, which means that Cocoa uses a secret class, different from the documented class you work with. You may discover this by peeking under the hood; for example, saying NSStringFromClass(s.dynamicType), where s is an NSString, might yield a mysterious value "__NSCFString". You should not spend any time wondering about this secret class. It is subject to change without notice and is none of your business; you should never have looked at it in the first place.

Property Lists

property list is a string (XML) representation of data. The Foundation classes NSString, NSData, NSArray, and NSDictionary are the only classes that can be converted into a property list. Moreover, an NSArray or NSDictionary can be converted into a property list only if the only classes it collects are these classes, along with NSDate and NSNumber. (This is why, as I mentioned earlier, you must convert a UIColor into an NSData in order to store it in user defaults; the user defaults is a property list.)

The primary use of a property list is to store data as a file. It is a way of serializing a value — saving it to disk in a form from which it can be reconstructed. NSArray and NSDictionary provide convenience methods writeToFile:atomically: and writeToURL:atomically: that generate property list files given a pathname or file URL, respectively; conversely, they also provide initializers that create an NSArray object or an NSDictionary object based on the property list contents of a given file. For this very reason, you are likely to start with one of these classes when you want to create a property list. (NSString and NSData, with their methods writeToFile:... and writeToURL:..., just write the data out as a file directly, not as a property list.)

When you reconstruct an NSArray or NSDictionary object from a property list file in this way, the collections, string objects, and data objects in the collection are all immutable. If you want them to be mutable, or if you want to convert an instance of one of the other property list classes to a property list, you’ll use the NSPropertyListSerialization class (see the Property List Programming Guide).

Accessors, Properties, and Key–Value Coding

An Objective-C instance variable is structurally similar to a Swift instance property: it’s a variable that accompanies each instance of a class, with a lifetime and value associated with that particular instance. An Objective-C instance variable, however, is usually private, in the sense that instances of other classes can’t see it (and Swift can’t see it). If an instance variable is to be made public, an Objective-C class will typically implement accessor methods: a getter and (if this instance variable is to be publicly writable) a setter. This is such a common thing to do that there are naming conventions:

The getter method

A getter should have the same name as the instance variable (without an initial underscore if the instance variable has one). Thus, if the instance variable is named myVar (or _myVar), the getter method should be named myVar.

The setter method

A setter method’s name should start with set, followed by a capitalized version of the instance variable’s name (without an initial underscore if the instance variable has one). The setter should take one parameter — the new value to be assigned to the instance variable. Thus, if the instance variable is named myVar (or _myVar), the setter should be named setMyVar:.

This pattern — a getter method, possibly accompanied by an appropriately named setter method — is so common that there’s a shorthand: an Objective-C class can declare a property, using the keyword @property and a name. Here, for example, is a line from the UIView class declaration:

@property(nonatomic) CGRect frame;

(Ignore the material in parentheses.) Within Objective-C, this declaration constitutes a promise that there is a getter accessor method frame returning a CGRect, along with a setter accessor method setFrame: that takes a CGRect parameter.

When Objective-C formally declares a @property in this way, Swift sees it as a Swift property. Thus, UIView’s frame property declaration is translated directly into a Swift declaration of an instance property frame of type CGRect:

var frame: CGRect

An Objective-C property name is mere syntactic sugar. When you set a UIView’s frame property, you are actually calling its setFrame: method, and when you get a UIView’s frame property, you are actually calling its frame method. In Objective-C, use of the property is optional; Objective-C can and does call the setFrame: and frame methods directly. In Swift, however, you can’t do that. If an Objective-C class has a formal @property declaration, the accessor methods are hidden from Swift.

Before Swift went public in June of 2014, Apple went through the APIs making sure that just about all accessor methods had corresponding @property declarations, so that Swift would be able to see them as properties. In a few cases, however, accessor methods remain, without a corresponding property. For example, here are two UIView instance method declarations:

- (BOOL)translatesAutoresizingMaskIntoConstraints;

- (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag;

It looks as if these are accessors for a translatesAutoresizingMaskIntoConstraints property; and in Objective-C, you can even pretend that there is such a property. But for some reason there is (as of this writing) no formal @property declaration fortranslatesAutoresizingMaskIntoConstraints — and so in Swift what you see are the two accessor methods and no property.

An Objective-C property declaration can include the word readonly in the parentheses. This indicates that there is a getter but no setter. So, for example (ignore the other material in the parentheses):

@property(nonatomic,readonly,retain) CALayer *layer;

Swift will reflect this restriction with {get} after the declaration, as if this were a computed read-only property; the compiler will not permit you to assign to such a property:

var layer: CALayer { get }

An Objective-C property and its accompanying accessor methods have a life of their own, independent of any underlying instance variable. Although accessor methods may literally be ways of accessing an invisible instance variable, they don’t have to be. When you set a UIView’s frameproperty and the setFrame: accessor method is called, you have no way of knowing what that method is really doing: it might be setting an instance variable called frame or _frame, but who knows? In this sense, accessors and properties are a façade, hiding the underlying implementation. This is similar to how, within Swift, you can set a variable without knowing or caring whether it is a stored variable or a computed variable; what setting the variable really does is unimportant (and possibly unknown) to the code that sets it.

Swift Accessors

Just as Objective-C properties are actually a shorthand for accessor methods, so Objective-C treats Swift properties as a shorthand for accessor methods — even though no such methods are formally present. If you, in Swift, declare that a class has a property prop, Objective-C can call aprop method to get its value or a setProp: method to set its value, even though you have not implemented such methods. Those calls are routed to your property through implicit accessor methods.

In Swift, you should not write explicit accessor methods for a property! Starting in Swift 1.2, the compiler will stop you if you attempt to do so. If you need to implement an accessor method explicitly and formally, use a computed property. Here, for example, I’ll add to my UIViewController subclass a computed color property with a getter and a setter:

class ViewController: UIViewController {

    var color : UIColor {

        get {

            println("someone called the getter")

            return UIColor.redColor()

        }

        set {

            println("someone called the setter")

        }

    }

}

If you arrange for Objective-C code to call explicitly the implicit setColor: and color accessor methods, you will see that the computed property’s setter and getter methods are in fact called:

ViewController* vc = [ViewController new];

[vc setColor:[UIColor redColor]]; // "someone called the setter"

UIColor* c = [vc color]; // "someone called the getter"

This proves that, in Objective-C’s mind, you have provided setColor: and color accessor methods. You can even change the Objective-C names of these accessor methods! To do so, add an @objc(...) attribute with the Objective-C name in parentheses. For example:

var color : UIColor {

    @objc(hue) get {

        println("someone called the getter")

        return UIColor.redColor()

    }

    @objc(setHue:) set {

        println("someone called the setter")

    }

}

It’s a little tricky, however, to prove that those really are the names of the accessor methods, because the names are not directly exposed to Objective-C as methods. I’ll work around that problem a little later.

If all you want to do is add functionality to the setter, use a property observer. For example, to add functionality to the Objective-C setFrame: method in your UIView subclass, you can override the frame property and write a setter observer:

class MyView: UIView {

    override var frame : CGRect {

        didSet {

            println("the frame setter was called: \(super.frame)")

        }

    }

}

Key–Value Coding

Cocoa can dynamically call an accessor — and thus can access a Swift property — based on a string name specified at runtime, through a mechanism called key–value coding (KVC). (This resembles, and is related to, the ability to use a selector name for introspection withrespondsToSelector:.) The string name is the key; what is passed to or returned from the accessor is the value. The basis for key–value coding is the NSKeyValueCoding protocol, an informal protocol; it is actually a category injected into NSObject. A Swift class, to be susceptible to key–value coding, must therefore be derived from NSObject.

The fundamental key–value coding methods are valueForKey: and setValue:forKey:. When one of these methods is called on an object, the object is introspected. In simplified terms, first the appropriate accessor is sought; if it doesn’t exist, the instance variable is accessed directly. Another useful pair of methods is dictionaryWithValuesForKeys: and setValuesForKeysWithDictionary:, which allow you to get and set multiple key–value pairs by way of an NSDictionary with a single command.

The value in key–value coding must be an Objective-C object — that is, it is typed as AnyObject. When calling valueForKey:, you’ll receive an Optional wrapping an AnyObject, which you’ll want to cast down safely to its expected type.

A class is key–value coding compliant (or KVC compliant) on a given key if it provides the accessor methods, or possesses the instance variable, required for access via that key. An attempt to access a key for which a class is not key–value coding compliant will cause an exception at runtime. It is useful to be familiar with the message you’ll get when such a crash occurs, so let’s cause it deliberately:

let obj = NSObject()

obj.setValue("howdy", forKey:"keyName") // crash

The console says: “This class is not key value coding-compliant for the key keyName.” The last word in that error message, despite the lack of quotes, is the key string that caused the trouble.

What would it take for that method call not to crash? The class of the object to which it is sent would need to have a setKeyName: setter method (or a keyName or _keyName instance variable). In Swift, as I demonstrated in the previous section, an instance property implies the existence of accessor methods. Thus, we can use key–value coding on an instance of any NSObject subclass that has a declared property, provided the key string is the string name of that property. Let’s try it! Here is such a class:

class Dog : NSObject {

    var name : String = ""

}

And here’s our test:

var d = Dog()

d.setValue("Fido", forKey:"name") // no crash!

println(d.name) // "Fido" - it worked!

UIViewController is derived from NSObject, so we can also use key–value coding to test our color accessor methods. Recall that I named them setHue: and hue:

var color : UIColor {

    @objc(hue) get {

        println("someone called the getter")

        return UIColor.redColor()

    }

    @objc(setHue:) set {

        println("someone called the setter")

    }

}

Now I have a way to call those accessors. Here, I’ll call the getter:

let c = self.valueForKey("hue") as? UIColor // "someone called the getter"

println(c) // Optional(UIDeviceRGBColorSpace 1 0 0 1)

Uses of Key–Value Coding

Key–value coding allows you, in effect, to decide at runtime, based on a string, what accessor to call. In the simplest case, you’re using a string to access a dynamically specified property. That’s useful in Objective-C code; but such unfettered introspective dynamism is contrary to the spirit of Swift, and in translating my own Objective-C code into Swift I have found myself accomplishing the same effect in other ways.

Here’s an example. In a flashcard app, I have a class Term, representing a Latin word. It declares many properties. Each card displays one term, with its various properties shown in different text fields. If the user taps any of three text fields, I want the interface to change from the term that’s currently showing to the next term whose value is different for the particular property that this text field represents. Thus this code is the same for all three text fields; the only difference is which property to consider as we hunt for the next term to be displayed. In Objective-C, by far the simplest way to express this parallelism is through key–value coding:

NSInteger tag = g.view.tag; // the tag tells us which text field was tapped

NSString* key = nil;

switch (tag) {

    case 1: key = @"lesson"; break;

    case 2: key = @"lessonSection"; break;

    case 3: key = @"lessonSectionPartFirstWord"; break;

}

// get current value of corresponding instance variable

NSString* curValue = [[self currentCardController].term valueForKey: key];

In Swift, however, it’s easy to implement the same dynamism using an array of anonymous functions:

let tag = g.view!.tag

let arr : [(Term) -> String] = [

    {$0.lesson}, {$0.lessonSection}, {$0.lessonSectionPartFirstWord}

]

let curValue = arr[tag-1](self.currentCardController.term)

Nevertheless, key–value coding remains valuable in Swift, especially because a number of built-in Cocoa classes permit you to use key–value coding in special ways. For example:

§  If you send valueForKey: to an NSArray, it sends valueForKey: to each of its elements and returns a new array consisting of the results, an elegant shorthand. NSSet behaves similarly.

§  NSDictionary implements valueForKey: as an alternative to objectForKey: (useful particularly if you have an NSArray of dictionaries). Similarly, NSMutableDictionary treats setValue:forKey: as a synonym for setObject:forKey:, except that value: can be nil, in which case removeObject:forKey: is called.

§  NSSortDescriptor sorts an NSArray by sending valueForKey: to each of its elements. This makes it easy to sort an array of dictionaries on the value of a particular dictionary key, or an array of objects on the value of a particular property.

§  NSManagedObject, used in conjunction with Core Data, is guaranteed to be key–value coding compliant for attributes you’ve configured in the entity model. Thus, it’s common to access those attributes with valueForKey: and setValue:forKey:.

§  CALayer and CAAnimation permit you to use key–value coding to define and retrieve the values for arbitrary keys, as if they were a kind of dictionary; this is extremely helpful for attaching identifying and configuration information to an instance of one of these classes. That, in fact, is my own most common way of using key–value coding in Swift.

KVC and Outlets

Key–value coding lies at the heart of how outlet connections work (Chapter 7). The name of the outlet in the nib is a string. It is key–value coding that turns the string into a hunt for a matching property at nib-loading time.

Suppose, for example, that you have a class Dog with an @IBOutlet property master, and you’ve drawn a "master" outlet from that class’s representative in the nib to a Person nib object. When the nib loads, the outlet name "master" is translated though key–value coding to the accessor method name setMaster:, and your Dog instance’s setMaster: implicit accessor method is called with the Person instance as its parameter — thus setting the value of your Dog instance’s master property to the Person instance (Figure 7-9).

If something goes wrong with the match between the outlet name in the nib and the name of the property in the class, then at runtime, when the nib loads, Cocoa’s attempt to use key–value coding to set a value in your object based on the name of the outlet will fail, and will generate an exception, complaining that the class is not key–value coding compliant for the key (the outlet name) — that is, your app will crash at nib-loading time. A likely way for this to happen is that you form the outlet correctly but then later change the name of (or delete) the property in the class (see Misconfigured Outlets).

Key Paths

key path allows you to chain keys in a single expression. If an object is key–value coding compliant for a certain key, and if the value of that key is itself an object that is key–value coding compliant for another key, you can chain those keys by calling valueForKeyPath: andsetValue:forKeyPath:. A key path string looks like a succession of key names joined using dot-notation. For example, valueForKeyPath("key1.key2)" effectively calls valueForKey: on the message receiver, with "key1" as the key, and then takes the object returned from that call and calls valueForKey: on that object, with "key2" as the key.

To illustrate this shorthand, imagine that our object myObject has an instance property theData which is an array of dictionaries such that each dictionary has a name key and a description key:

var theData = [

    [

        "description" : "The one with glasses.",

        "name" : "Manny"

    ],

    [

        "description" : "Looks a little like Governor Dewey.",

        "name" : "Moe"

    ],

    [

        "description" : "The one without a mustache.",

        "name" : "Jack"

    ]

]

We can use key–value coding with a key path to drill down into that array of dictionaries:

let arr = myObject.valueForKeyPath("theData.name") as! [String]

The result is an array consisting of the strings "Manny", "Moe", and "Jack". If you don’t see why, review what I said earlier about how NSArray and NSDictionary implement valueForKey:.

TIP

Recall also the discussion of user-defined runtime attributes, in Chapter 7. This feature uses key–value coding! The key you’re entering when you define a runtime attribute in an object’s Identity inspector in a nib is actually a key path.

Array Accessors

Key–value coding is a powerful technology with many additional ramifications. (See Apple’s Key-Value Coding Programming Guide for full information.) I’ll illustrate just one of them. Key–value coding allows an object to synthesize a key whose value appears to be an array (or a set), even if it isn’t. You implement specially named accessor methods; key–value coding sees them when you try to use the corresponding key.

To illustrate, I’ll add these methods to the class of our object myObject:

func countOfPepBoys() -> Int {

    return self.theData.count

}

func objectInPepBoysAtIndex(ix:Int) -> AnyObject {

    return self.theData[ix]

}

By implementing countOf... and objectIn...AtIndex:, I’m telling the key–value coding system to act as if the given key — "pepBoys", in this case — exists and is an array. An attempt to fetch the value of the key "pepBoys" by way of key–value coding will succeed, and will return an object that can be treated as an NSArray, though in fact it is a proxy object (an NSKeyValueArray). Thus we can now say things like this:

let arr = myObject.valueForKey("pepBoys")!

let arr2 = myObject.valueForKeyPath("pepBoys.name")!

In that code, arr is the array proxy, and arr2 is the same array of the names of the three Pep Boys as before. The example seems pointless: the underlying implementation is already an array, so how does this differ from saying myObject.valueForKey("theData") andmyObject.valueForKeyPath("theData.name")? It doesn’t. But it could! Imagine that there is no simple actual array — that the result of countOfPepBoys and objectInPepBoysAtIndex: is obtained through some completely different sort of operation. In effect, we have created a key that poses as an NSArray; we could have anything at all hiding behind it.

(The proxy object returned through this sort of façade behaves like an NSArray, not like an NSMutableArray. If you want the caller to be able to manipulate the proxy object provided by a KVC façade as if it were an NSMutableArray, you must implement two more methods, and the caller must obtain a different proxy object by calling mutableArrayValueForKey:.)

The Secret Life of NSObject

Because every Objective-C class inherits from NSObject, it’s worth taking some time to explore NSObject. NSObject is constructed in a rather elaborate way:

§  It defines some native class methods and instance methods having mostly to do with the basics of instantiation and of method sending and resolution. (See the NSObject Class Reference.)

§  It adopts the NSObject protocol. This protocol declares instance methods having mostly to do with memory management, the relationship between an instance and its class, and introspection. Because all the NSObject protocol methods are required, the NSObject class implements them all. (See the NSObject Protocol Reference.) In Swift, the NSObject protocol is called NSObjectProtocol, to avoid name clash.

§  It implements convenience methods related to the NSCopying, NSMutableCopying, and NSCoding protocols, without formally adopting those protocols. NSObject intentionally doesn’t adopt these protocols because this would cause all other classes to adopt them, which would be wrong. But thanks to this architecture, if a class does adopt one of these protocols, you can call the corresponding convenience method. For example, NSObject implements the copy instance method, so you can call copy on any instance, but you’ll crash unless the instance’s class also adopts the NSCopying protocol and implements copyWithZone:.

§  A large number of methods are injected into NSObject by more than two dozen categories on NSObject, scattered among various header files. For example, awakeFromNib (see Chapter 7) comes from the UINibLoadingAdditions category on NSObject, declared in UINibLoading.h.

§  A class object is an object. Therefore all Objective-C classes, which are objects of type Class, inherit from NSObject. Therefore, any method defined as an instance method by NSObject can be called on a class object as a class method! For example, respondsToSelector: is defined as an instance method by NSObject, but it can (therefore) be treated also as a class method and sent to a class object.

The problem for the programmer is that Apple’s documentation is rather rigid about classification. When you’re trying to work out what you can say to an object, you don’t care where that object’s methods come from; you just care what you can say. But the documentation differentiates methods by where they come from. As a result, even though NSObject is the root class, the most important class, from which all other classes inherit, no single page of the documentation provides a conspectus of all its methods. Instead, you have to look at both the NSObject Class Referenceand the NSObject Protocol Reference simultaneously, plus the pages documenting the NSCopying, NSMutableCopying, and NSCoding protocols (in order to understand how they interact with methods defined by NSObject), plus you have to supply mentally a class method version of every NSObject instance method!

Then there are the methods injected into NSObject by categories. Some that are general in nature are documented on the NSObject class documentation page itself; for example, awakeAfterUsingCoder: comes from a category declared in a separate header, but it is documented under NSObject, quite rightly, since this is a class method, and therefore effectively a global method, that you might want to send at any time. Others are delegate methods used in restricted situations (so that these are really informal protocols), and do not need centralized documentation; for example, animationDidStart: is documented under the CAAnimation class, quite rightly, because you need to know about it only and exactly when you’re working with CAAnimation. However, every object responds to awakeFromNib, and it’s likely to be crucial to every app you write; yet you must learn about it outside of the NSObject documentation, sitting all by itself in the NSObject UIKit Additions Reference page, where you’re extremely unlikely to discover it! The same goes, it might be argued, for all the key–value coding methods (see earlier in this chapter) and key–value observing methods (Chapter 11).

Once you’ve collected, by hook or by crook, all the NSObject methods, you can see that they fall into a certain natural classification:

Creation, destruction, and memory management

Methods for creating an instance, such as alloc and copy, along with methods for learning when something is happening in the lifetime of an object, such as initialize and dealloc, plus methods that manage memory.

Class relationships

Methods for learning an object’s class and inheritance, such as superclass, isKindOfClass:, and isMemberOfClass:.

Object introspection and comparison

Methods for asking what would happen if an object were sent a certain message, such as respondsToSelector:, for representing an object as a string (description), and for comparing objects (isEqual:).

Message response

Methods for meddling with what does happen when an object is sent a certain message, such as doesNotRecognizeSelector:. If you’re curious, see the Objective-C Runtime Programming Guide.

Message sending

Methods for sending a message dynamically, mostly starting with performSelector:...; these methods are generally unavailable in Swift.