Cocoa Events - Cocoa - iOS 8 Programming Fundamentals with Swift: Swift, Xcode, and Cocoa Basics (2015)

iOS 8 Programming Fundamentals with Swift: Swift, Xcode, and Cocoa Basics (2015)

Part III. Cocoa

Chapter 11. Cocoa Events

All of your app’s executable code lies in its functions. The impetus for a function being called must come from somewhere. One of your functions may call another, but who will call the first function in the first place? How, ultimately, will any of your code ever run? As I said in Chapter 6, after your app has launched, “UIApplicationMain is just sitting there, watching for the user to do something, maintaining the event loop, which will respond to user actions as they occur.”

The event loop is the key. The runtime is watching and waiting for certain things to happen, such as the user making a gesture on the screen, or some specific stage arriving in the lifetime of your app. When such things do happen, the runtime calls your code. But the runtime can call your code only if your code is there to be called. Your code is like a panel of buttons, waiting for Cocoa to press one. If something happens that Cocoa feels your code needs to know about and respond to, it presses the right button — if the right button is there.

The art of Cocoa programming lies in knowing what Cocoa wants to do. You organize your code, right from the start, with Cocoa’s behavior in mind. Cocoa makes certain promises about how and when it will dispatch messages to your code. These are Cocoa’s events. You know what these events are, and you arrange for your code to be ready when Cocoa delivers them.

The specific events that you can receive are listed in the documentation. The overall architecture of how and when events are dispatched and the ways in which your code arranges to receive them is the subject of this chapter.

Reasons for Events

Broadly speaking, the reasons you might receive an event may be divided informally into four categories. These categories are not official; I made them up. Often it isn’t completely clear which of these categories an event fits into; an event may well appear to fit two categories. But they are still generally useful for visualizing how and why Cocoa interacts with your code:

User events

The user does something interactive, and an event is triggered directly. Obvious examples are events that you get when the user taps or swipes the screen, or types a key on the keyboard.

Lifetime events

These are events notifying you of the arrival of a stage in the life of the app, such as the fact that the app is starting up or is about to go into the background, or of a component of the app, such as the fact that a UIViewController’s view has just loaded or is about to be removed from the screen.

Functional events

Cocoa is about to do something, and turns to you in case you want to supply additional functionality. I would put into this category UIView’s drawRect: (your chance to have a view draw itself) and UILabel’s drawTextInRect: (your chance to modify the look of a label), with which we experimented in Chapter 10.

Query events

Cocoa turns to you to ask a question; its behavior will depend upon your answer. For example, the way data appears in a table (a UITableView) is that whenever Cocoa needs a cell for a row of the table, it turns to you and asks for the cell.

Subclassing

A built-in Cocoa class may define methods that Cocoa itself will call and that you are invited (or required) to override in a subclass, so that your custom behavior, and not (merely) the default behavior, will take place.

An example I gave in Chapter 10 was UIView’s drawRect:. This is what I call a functional event. By overriding drawRect: in a UIView subclass, you dictate the full procedure by which a view draws itself. You don’t know exactly when this method will be called, and you don’t care; when it is, you draw, and this guarantees that the view will always appear the way you want it to. (You never call drawRect: yourself; if some underlying condition has changed and you want the view to be redrawn, you call setNeedsDisplay and let Cocoa call drawRect: in response.)

Built-in UIView subclasses may have other functional event methods you’ll want to customize through subclassing. Typically this will be in order to change the way the view is drawn, without taking command of the entire drawing procedure yourself. In Chapter 10 I gave an example involving UILabel and its drawTextInRect:. A similar case is UISlider, which lets you customize the position and size of the slider’s “thumb” by overriding thumbRectForBounds:trackRect:value:.

UIViewController is a class meant for subclassing. Of the methods listed in the UIViewController class documentation, just about all are methods you might have reason to override. If you create a UIViewController subclass in Xcode, you’ll see that the template already includes a couple of method overrides to get you started. For example, viewDidLoad is called to let you know that your view controller has obtained its main view (its view), so that you can perform initializations; it’s an obvious example of a lifetime event. And UIViewController has many other lifetime events that you can and will override in order to get fine control over what happens when. For example, viewWillAppear: means that your view controller’s view is about to be placed into the interface; viewDidAppear: means that your view controller’s view has been placed into the interface; viewDidLayoutSubviews means that your view has been positioned within its superview; and so on.

A UIViewController method like supportedInterfaceOrientations is what I call a query event. Your job is to return a bitmask telling Cocoa what orientations your view can appear in at this moment — whenever that may be. You trust Cocoa to call this method at the appropriate moments, so that if the user rotates the device, your app’s interface will or won’t be rotated to compensate, depending on what value you return.

When looking for events that you can receive through subclassing, be sure to look upward though the inheritance hierarchy. For example, if you’re wondering how to be notified when your custom UILabel subclass is embedded into another view, you won’t find the answer in the UILabel class documentation; a UILabel receives the appropriate event by virtue of being a UIView. In the UIView class documentation, you’ll learn that you can override didMoveToSuperview to be informed when this happens. By the same token, look upward through adopted protocols as well. In iOS 8, if you’re wondering how to be notified when your view controller’s view is about to undergo app rotation, you won’t find out by looking in the UIViewController class documentation; a UIViewController receives the appropriate event by virtue of adopting the UIContentContainer prototocol. In the UIContentContainer protocol documentation, you’ll learn that you can override viewWillTransitionToSize:withTransitionCoordinator:.

Nevertheless, as I said in Chapter 10, subclassing and overriding is far from being the most important or commmon way of arranging to receive events. Aside from UIViewController, it is hard to think of any built-in Cocoa class that you will regularly subclass for this purpose. So what are the other ways in which your code receives events? That’s what the rest of this chapter is about.

Notifications

Cocoa provides your app with a single instance of NSNotificationCenter, informally called the notification center. This instance, available by calling NSNotificationCenter.defaultCenter(), is the basis of a mechanism for sending messages called notifications. A notification is an instance of NSNotification. The idea is that any object can be registered with the notification center to receive certain notifications. Another object can hand the notification center a notification to send out (this is called posting the notification). The notification center will then send that notification to all objects that are registered to receive it.

The notification mechanism is often described as a dispatching or broadcasting mechanism, and with good reason. It lets an object send a message without knowing or caring what object or how many objects receive it. This relieves your app’s architecture from the formal responsibility of somehow hooking up instances just so a message can pass from one to the other (which can sometimes be quite tricky or onerous, as discussed in Chapter 13). When objects are conceptually “distant” from one another, notifications can be a fairly lightweight way of permitting one to message the other.

An NSNotification instance has three pieces of information associated with it, which can be retrieved by instance methods:

name

An NSString which identifies the notification’s meaning.

object

An instance associated with the notification; typically, the instance that posted it.

userInfo

Not every notification has a userInfo; it is an NSDictionary, and can contain additional information associated with the notification. What information this NSDictionary will contain, and under what keys, depends on the particular notification; you have to consult the documentation. For example, the documentation tells us that UIApplication’s UIApplicationDidChangeStatusBarOrientationNotification includes a userInfo dictionary with a key UIApplicationStatusBarOrientationUserInfoKey whose value is the status bar’s previous orientation. When you post a notification yourself, you can put anything you like into the userInfo for the notification’s recipient(s) to retrieve.

Cocoa itself posts notifications through the notification center, and your code can register to receive them. You’ll find a separate Notifications section in the documentation for a class that provides them.

Receiving a Notification

To register to receive a notification, you send one of two messages to the notification center. One is addObserver:selector:name:object:. The parameters are as follows:

observer:

The instance to which the notification is to be sent. This will typically be self; it would be quite unusual for one instance to register a different instance as the receiver of a notification.

selector:

The message to be sent to the observer instance when the notification occurs. The designated method should return no result (Void) and should take one parameter, which will be the NSNotification instance (so the parameter should be typed as NSNotification or AnyObject). In Swift, you specify the selector by giving the name of the method as a string; see Appendix A for the rules about how to turn a method into a string name.

Don’t get the string name of this method wrong, and don’t forget to implement the method! If the notification center sends a notification by trying to call the method specified as the selector:, and if that exact method doesn’t exist, your app will crash.

The method named by this selector cannot be called unless it is exposed to Objective-C. If the notification center sends a notification by trying to call the method specified as the selector:, and if Objective-C can’t see that method, your app will crash. Objective-C can see the method if the class is a subclass of NSObject, or if the class is marked @objc, or if the method is marked @objc.

name:

The string name of the notification you’d like to receive. If this parameter is nil, you’re asking to receive all notifications associated with the object designated in the object: parameter. A built-in Cocoa notification’s name is usually a constant. This is helpful, because if you flub the name of a constant, the compiler will complain, whereas if you enter the name of the notification directly as string literal and you get it wrong, the compiler won’t complain but you will mysteriously fail to get any notifications (because no notification has the name you actually entered) — a very difficult sort of mistake to track down.

object:

The object of the notification you’re interested in, which will usually be the object that posted it. If this is nil, you’re asking to receive all notifications with the name designated in the name: parameter. (If both the name: and object: parameters are nil, you’re asking to receive all notifications!)

For example, in one of my apps I want to change the interface whenever the device’s music player starts playing a different song. The API for the device’s built-in music player belongs to the MPMusicPlayerController class; this class provides a notification to tell me when the built-in music player changes what song is being played, listed under Notifications in the MPMusicPlayerController class documentation as MPMusicPlayerControllerNowPlayingItemDidChangeNotification.

It turns out, looking at the documentation, that this notification won’t be posted at all unless I first call MPMusicPlayerController’s beginGeneratingPlaybackNotifications instance method. This architecture is not uncommon; Cocoa saves itself some time and effort by not sending out certain notifications unless they are switched on, as it were. So my first job is to get an instance of MPMusicPlayerController and call this method:

let mp = MPMusicPlayerController.systemMusicPlayer()

mp.beginGeneratingPlaybackNotifications()

Now I register myself to receive the desired playback notification:

NSNotificationCenter.defaultCenter().addObserver(self,

selector: "nowPlayingItemChanged:",

name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification,

object: nil)

So now, whenever an MPMusicPlayerControllerNowPlayingItemDidChangeNotification is posted, my nowPlayingItemChanged: method will be called:

func nowPlayingItemChanged (n:NSNotification) {

self.updateNowPlayingItem()

// ... and so on ...

}

For addObserver:selector:name:object: to work properly, you must get the selector right and make sure you implement the corresponding method. Heavy use of addObserver:selector:name:object: means that your code ends up peppered with methods that exist solely in order to be called by the notification center. There is nothing about these methods that tells you what they are for — you will probably want to use explicit comments in order to remind yourself — and the methods are separate from the registration call, all of which makes your code rather confusing.

This problem is solved by using the other way of registering to receive a notification — by calling addObserverForName:object:queue:usingBlock:. It returns a value, whose purpose I’ll explain in a moment. The queue: will usually be nil; a non-nil queue: is for background threading. The name: and object: parameters are just like those of addObserver:selector:name:object:. Instead of an observer and a selector, you provide a block (a Swift function) consisting of the actual code to be executed when the notification arrives. This function should take one parameter — the NSNotification itself. If you use an anonymous function, your response to the notification being posted happens right there in the body of that function:

let ob = NSNotificationCenter.defaultCenter()

.addObserverForName(

MPMusicPlayerControllerNowPlayingItemDidChangeNotification,

object: nil, queue: nil) {

_ in

self.updateNowPlayingItem()

// ... and so on ...

}

Use of addObserverForName:... imposes some additional memory management complications that I’ll talk about in Chapter 12.

Unregistering

It is up to you, for every object that you register as a recipient of notifications, to unregister that object before it goes out of existence. If you fail to do this, and if the object does go out of existence, and if a notification for which that object is registered is posted, the notification center will attempt to send the appropriate message to that object, which is now missing in action. The result will be a crash at best, and chaos at worst.

To unregister an object as a recipient of notifications, send the notification center the removeObserver: message. (Alternatively, you can unregister an object for just a specific set of notifications with removeObserver:name:object:.) The object passed as the observer: argument is the object that is no longer to receive notifications. What object that is depends on how you registered in the first place:

You called addObserver:...

You supplied an observer originally; that is the observer you must now unregister.

You called addObserverForName:...

The call to addObserverForName:... returned an observer token object typed as an NSObjectProtocol (its real class and nature are no concern of yours); that is the observer you must now unregister.

The trick is finding the right moment to unregister. The fallback solution is the registered instance’s deinit method, this being the last lifetime event an instance is sent before it goes out of existence.

If you’re calling addObserverForName:... multiple times from the same class, you’re going to end up receiving from the notification center multiple observer tokens, which you need to preserve so that you can unregister all of them later. If your plan is to unregister everything at once, one way to handle this situation is through an instance property that is a mutable collection. My favored approach is a Set property called observers:

var observers = Set<NSObject>()

Each time I register for a notification using addObserverForName..., I capture the result and add it to the set:

let ob = NSNotificationCenter.defaultCenter().addObserverForName(...)

self.observers.insert(ob as! NSObject)

When it’s time to unregister, I enumerate the set and empty it:

for ob in self.observers {

NSNotificationCenter.defaultCenter().removeObserver(ob)

}

self.observers.removeAll()

WARNING

NSNotificationCenter cannot be introspected: you cannot ask an NSNotificationCenter what objects are registered with it as notification recipients. This is a major gap in Cocoa’s functionality, and can make it difficult to track down bugs if you make a mistake such as unregistering an observer prematurely (as usual, I know this from bitter experience).

Posting a Notification

Although you’ll mostly be interested in receiving notifications from Cocoa, you can also take advantage of the notification mechanism as a way of communicating between your own objects. One reason for doing this might be that two objects are conceptually distant or independent from one another. You should probably avoid using notifications too freely, or as an excuse for devising proper lines of communication between objects; but they are certainly appropriate in some circumstances. (I’ll raise this point again in Chapter 13.)

To use notifications in this way, your objects must play both roles in the communication chain. One of your objects (or more than one) will register to receive a notification, identified by name or object or both, as I’ve already described. Another of your objects will post a notification, identified in the same way. The notification center will then pass the message along from the poster to the registered recipient(s).

To post a notification, send to the notification center the message postNotificationName:object:userInfo:.

For example, one of my apps is a simple card game. The game needs to know when a card is tapped. But a card knows nothing about the game; when it is tapped, it simply emits a virtual shriek by posting a notification:

func singleTap(_:AnyObject) { // select me

NSNotificationCenter.defaultCenter()

.postNotificationName("cardTapped", object: self)

}

The game object has registered for the "cardTapped" notification, so it hears about this and retrieves the notification’s object; now it knows what card was tapped and can proceed correctly.

NSTimer

A timer (NSTimer) is not, strictly speaking, a notification; but it behaves very similarly. It is an object that gives off a signal (fires) after the lapse of a certain time interval. The signal is a message to one of your instances. Thus you can arrange to be notified when a certain time has elapsed. The timing is not perfectly accurate, but it’s pretty good.

Timer management is not exactly tricky, but it is a little unusual. A timer that is actively watching the clock is said to be scheduled. A timer may fire once, or it may be a repeating timer. To make a timer go out of existence, it must be invalidated. A timer that is set to fire once is invalidated automatically after it fires; a repeating timer repeats until you invalidate it by sending it the invalidate message. An invalidated timer should be regarded as off-limits: you cannot revive it or use it for anything further, and you should probably not send any messages to it.

The straightforward way to create a timer is with the NSTimer class method scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:. This both creates the timer and schedules it, so that it begins watching the clock immediately. The target and selector determine what message will be sent to what object when the timer fires; the method in question should take one parameter, which will be a reference to the timer. The userInfo is just like the userInfo of a notification.

An NSTimer has a tolerance property, which is a time interval signifying a how long after the timer would fire you’re willing to grant before it really does fire. The documentation suggests that you can improve device battery life and app responsiveness by supplying a value of at least 10 percent of the timeInterval.

For example, one of my apps is a game with a score; I want to penalize the user, by diminishing the score, for every ten seconds after each move that elapses without the user making a further move. So each time the user makes a move, I create a repeating timer whose time interval is ten seconds (and I also invalidate any existing timer); in the method that the timer calls, I diminish the score.

Timers have some memory management implications that I’ll discuss in Chapter 12, along with a block-based alternative to a timer.

Delegation

Delegation is an object-oriented design pattern, a relationship between two objects, in which a primary object’s behavior is customized or assisted by a secondary object. The secondary object is the primary object’s delegate. No subclassing is involved, and indeed the primary object is agnostic about the delegate’s class.

As implemented by Cocoa, here’s how delegation works. A built-in Cocoa class has an instance property, usually called delegate (it will certainly have delegate in its name). For some instance of that Cocoa class, you set the value of this property to an instance of one of your classes. At certain moments in its activity, the Cocoa class promises to turn to its delegate for instructions by sending it a certain message: if the Cocoa instance finds that its delegate is not nil, and that its delegate is prepared to receive that message, the Cocoa instance sends the message to the delegate.

Recall the discussion of protocols from Chapter 10. Delegation is one of Cocoa’s main uses of protocols. In the old days, delegate methods were listed in the Cocoa class’s documentation, and their method signatures were made known to the compiler through an informal protocol (a category on NSObject). Now, though, a class’s delegate methods are usually listed in a genuine protocol with its own documentation. There are over 70 Cocoa delegate protocols, showing how heavily Cocoa relies on delegation. Most delegate methods are optional, but in a few cases you’ll discover some that are required.

Cocoa Delegation

To customize a Cocoa instance’s behavior through delegation, you start with one of your classes, which adopts the relevant delegate protocol. When the app runs, you set the Cocoa instance’s delegate property (or whatever its name is) to an instance of your class. You might do this in code; alternatively, you might do it in a nib, by connecting an instance’s delegate outlet (or whatever it’s called) to an appropriate instance that is to serve as delegate. Your delegate class will probably do other things besides serving as this instance’s delegate. Indeed, one of the nice things about delegation is that it leaves you free to slot delegate code into your class architecture however you like; the delegate type is a protocol, so the actual delegate can be an instance of any class.

In this simple example, I want to ensure that my app’s root view controller, a UINavigationController, doesn’t permit the app to rotate — the app should appear only in portrait orientation when this view controller is in charge. But UINavigationController isn’t my class; it belongs to Cocoa. My own class is a different view controller, a UIViewController subclass, which acts as the UINavigationController’s child. How can the child tell the parent how to rotate? Well, UINavigationController has a delegate property, typed as UINavigationControllerDelegate (a protocol). It promises to send this delegate the navigationControllerSupportedInterfaceOrientations message when it needs to know how to rotate. So my view controller, in response to a very early lifetime event, sets itself as the UINavigationController’s delegate. It also implements the navigationControllerSupportedInterfaceOrientations method. Presto, the problem is solved:

class ViewController : UIViewController, UINavigationControllerDelegate {

override func viewDidLoad() {

super.viewDidLoad()

self.navigationController!.delegate = self

}

func navigationControllerSupportedInterfaceOrientations(

navigationController: UINavigationController) -> Int {

return Int(UIInterfaceOrientationMask.Portrait.rawValue)

}

}

An app’s shared application instance, UIApplication.sharedApplication(), has a delegate that serves such an important role in the life of the app that the Xcode app templates automatically supply one — a class called AppDelegate. I described in Chapter 6 how an app gets started by calling UIApplicationMain, which instantiates the AppDelegate class and makes that instance the delegate of the shared application instance (which it has also created). As I pointed out in Chapter 10, AppDelegate formally adopts the UIApplicationDelegate protocol, signifying that it is ready to serve in this role; respondsToSelector: is then sent to the app delegate to see what UIApplicationDelegate protocol methods it implements. Thereafter, the application delegate instance is sent messages letting it know of major events in the lifetime of the app. That is why the UIApplicationDelegate protocol method application:didFinishLaunchingWithOptions: is so important; it is one of the earliest opportunities for your code to run.

TIP

The UIApplication delegate methods are also provided as notifications. This lets an instance other than the app delegate hear conveniently about application lifetime events, by registering for them. A few other classes provide duplicate events similarly; for example, UITableView’s tableView:didSelectRowAtIndexPath: delegate method is matched by a notificationUITableViewSelectionDidChangeNotification.

By convention, many Cocoa delegate method names contain the modal verbs should, will, or did. A will message is sent to the delegate just before something happens; a did message is sent to the delegate just after something happens. A should method is special: it returns a Bool, and you are expected to respond with true to permit something or false to prevent it. The documentation tells you what the default response is; you don’t have to implement a should method if the default response is always acceptable.

In many cases, a property will control some overall behavior, while a delegate method lets you modify that behavior based on circumstances at runtime. For example, whether the user can tap the status bar to make a scroll view scroll quickly to the top is governed by the scroll view’sscrollsToTop property; but even if this property’s value is true, you can prevent this behavior for a particular tap by returning false from the scroll view delegate’s scrollViewShouldScrollToTop:.

When you’re searching the documentation for how you can be notified of a certain event, be sure to consult the corresponding delegate protocol, if there is one. You’d like to know when the user taps in a UITextField to start editing it? You won’t find anything relevant in the UITextField class documentation; what you’re after is textFieldDidBeginEditing: in the UITextFieldDelegate protocol. And so on.

Implementing Delegation

The Cocoa pattern of a delegate whose responsibilities are described by a protocol is one that you will want to imitate in your own code. Setting up this pattern takes some practice, and can be a little time-consuming, but it is often the correct approach, because it appropriately assigns knowledge and responsibility to the various objects involved.

A very typical situation is a case of two-way communication. Object A creates and configures Object B; later, before Object B goes out of existence, Object A also needs to hear back from Object B. The pattern here is that Class B declares a protocol SomeProtocol, along with a delegateproperty typed as SomeProtocol. That way, Class B needn’t know anything about Class A. Class A adopts SomeProtocol and implements its required methods. When Object A creates Object B, it also sets itself as Object B’s delegate. Now Object B knows all that it needs to know: it can send SomeProtocol messages to its delegate, regardless of that delegate’s actual class.

To see why this pattern is a good one, consider an actual case. In one of my apps I present a view controller whose view contains three sliders that the user can move to choose a color. Appropriately, this view controller is a UIViewController subclass called ColorPickerController. When the user taps Done or Cancel, the view should be dismissed; but first, the code that presented this view needs to hear about what color the user chose. So I need to send a message from the ColorPickerController instance back to the instance that presented it. This is exactly the two-way communication problem I just described.

Here is the declaration for the message that I want the ColorPickerController to send before it goes out of existence:

func colorPicker (picker:ColorPickerController,

didSetColorNamed theName:String?,

toColor theColor:UIColor?)

The question is: where and how should this method be declared?

Now, it happens that in my app I know the class of the instance that will in fact present the ColorPickerController: it is a SettingsController. So I could simply declare this method in SettingsController. But this, if it is all I do, means that the ColorPickerController, in order to send this message to the SettingsController, must know that the view that presented it is a SettingsController. But surely it is merely a contingent fact that the instance being sent this message is a SettingsController; it should be open to any class to present and dismiss a ColorPickerController, and thus to be eligible to receive this message.

Therefore we want ColorPickerController itself to declare the method that it itself is going to call; and we want it to send the message blindly to some receiver, without regard to the class of that receiver. That’s what a protocol is for! The solution, then, is for ColorPickerController to define a protocol, with this method as part of that protocol, and for the class that presents a ColorPickerController to conform to that protocol. ColorPickerController also has an appropriately typed delegate property; this provides the channel of communication, and tells the compiler that sending this message is legal:

protocol ColorPickerDelegate : class {

// color == nil on cancel

func colorPicker (picker:ColorPickerController,

didSetColorNamed theName:String?,

toColor theColor:UIColor?)

}

class ColorPickerController : UIViewController {

weak var delegate: ColorPickerDelegate?

// ...

}

(On the meaning of and reasons for the weak attribute, see Chapter 5.) When my SettingsController instance creates and configures a ColorPickerController instance, it also sets itself as that ColorPickerController’s delegate:

extension SettingsController : ColorPickerDelegate {

func showColorPicker() {

let colorName = // ...

let c = // ...

let cpc = ColorPickerController(colorName:colorName, andColor:c)

cpc.delegate = self

// ... and present the color picker controller ...

}

}

Now, when the user picks a color, the ColorPickerController knows to whom it should send colorPicker:didSetColorNamed:toColor: — namely, its delegate! And the compiler allows this, because the delegate has adopted the ColorPickerDelegate protocol:

func dismissColorPicker(sender : AnyObject?) { // user tapped Done

var c : UIColor? = self.color

self.delegate?.colorPicker(

self, didSetColorNamed: self.colorName, toColor: c)

}

Data Sources

A data source is like a delegate, except that its methods supply the data for another object to display. The chief Cocoa classes with data sources are UITableView, UICollectionView, UIPickerView, and UIPageViewController. In each case, the data source must formally adopt a data source protocol with required methods.

It comes as a surprise to some beginners that a data source is necessary at all. Why isn’t a table’s data just part of the table? Or why isn’t there at least some fixed data structure that contains the data? The reason is that such an architecture would violate generality. Use of a data source separates the object that displays the data from the object that manages the data, and leaves the latter free to store and obtain that data however it likes (see on model–view–controller in Chapter 13). The only requirement is that the data source must be able to supply information quickly, because it will be asked for it in real time when the data needs displaying.

Another surprise is that the data source is different from the delegate. But this again is only for generality; it’s an option, not a requirement. There is no reason why the data source and the delegate should not be the same object, and most of the time they probably will be. Indeed, in most cases, data source methods and delegate methods will work closely together; you won’t even be conscious of the distinction.

In this example from one of my apps, I implement a UIPickerView that allows the user to configure a game by saying how many stages it should consist of (“1 Stage,” “2 Stages”, and so on). The first two methods are UIPickerView data source methods; the third method is a UIPickerView delegate method. It takes all three methods to supply the picker view’s content:

extension NewGameController: UIPickerViewDelegate, UIPickerViewDataSource {

func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {

return 1

}

func pickerView(pickerView: UIPickerView,

numberOfRowsInComponent component: Int) -> Int {

return 9

}

func pickerView(pickerView: UIPickerView,

titleForRow row: Int, forComponent component: Int) -> String? {

return "\(row+1) Stage" + ( row > 0 ? "s" : "")

}

}

Actions

An action is a message emitted by an instance of a UIControl subclass (a control) reporting a significant user event taking place in that control (see Chapter 7). The UIControl subclasses are all simple interface objects that the user can interact with directly, such as a button (UIButton) or a segmented control (UISegmentedControl).

The significant user events (control events) are listed under UIControlEvents in the Constants section of the UIControl class documentation. Different controls implement different control events: for example, a segmented control’s Value Changed event signifies that the user has tapped to select a different segment, but a button’s Touch Up Inside event signifies that the user has tapped the button. Of itself, a control event has no external effect; the control responds visually (for example, a tapped button looks tapped), but it doesn’t automatically share the information that the event has taken place. If you want to know when a control event takes place, so that you can respond to it in your code, you must arrange for that control event to trigger an action message.

Here’s how it works. A control maintains an internal dispatch table: for each control event, there can be any number of target–action pairs, in each of which the action is a message selector (the name of a method) and the target is the object to which that message is to be sent. When a control event occurs, the control consults its dispatch table, finds all the target–action pairs associated with that control event, and sends each action message to the corresponding target (Figure 11-1).

The target–action architecture

Figure 11-1. The target–action architecture

There are two ways to manipulate a control’s action dispatch table:

Action connection

You can configure an action connection in a nib. I described in Chapter 7 how to do this, but I didn’t completely explain the underlying mechanism. Now all is revealed: an action connection formed in the nib editor is a visual way of configuring a control’s action dispatch table.

Code

You can use code to operate directly on the control’s action dispatch table. The key method here is the UIControl instance method addTarget:action:forControlEvents:, where the target: is an object, the action: is a selector (in Swift, a string), and the controlEvents:are designated by a bitmask (see Chapter 3 if you’ve forgotten how to construct a bitmask). Unlike a notification center, a control also has methods for introspecting the dispatch table.

Recall the example of a control and its action from Chapter 7. We have a buttonPressed: method:

@IBAction func buttonPressed(sender:AnyObject) {

let alert = UIAlertController(

title: "Howdy!", message: "You tapped me!", preferredStyle: .Alert)

alert.addAction(

UIAlertAction(title: "OK", style: .Cancel, handler: nil))

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

}

The purpose of this method is to be called when the user taps a certain button in the interface. In Chapter 7, we arranged for that to happen by setting up an action connection in the nib: we connected the button’s Touch Up Inside event to the ViewController buttonPressed: method. In reality, this meant that we were forming a target–action pair — the target is the ViewController instance that will function as the nib owner when the nib is loaded, and the action is the buttonPressed: selector — and adding that target–action pair to the button’s dispatch table for the Touch Up Inside control event.

Instead of making that arrangement in the nib, we could have done the same thing in code. Suppose we had never drawn that action connection. And suppose that, instead, we had an outlet connection from the view controller to the button, called button. Then the view controller, after the nib loads, can configure the button’s dispatch table like this:

self.button.addTarget(self,

action: "buttonPressed:",

forControlEvents: .TouchUpInside)

WARNING

A control event can have multiple target–action pairs. You might configure it this way intentionally, but it is also possible to do so accidentally. Unintentionally giving a control event a target–action pair without removing its existing target-action pair is an easy mistake to make, and can cause some very mysterious behavior. For example, if we had formed an action connection in the nib and configured the dispatch table in code, a tap on the button would cause buttonPressed: to be called twice.

The signature for the action selector can be in any of three forms:

§ The fullest form takes two parameters:

§ The control, usually typed as AnyObject.

§ The UIEvent that generated the control event.

§ A shorter form, the one most commonly used, omits the second parameter. buttonPressed: is an example; it takes one parameter, sender. When buttonPressed: is called through an action message emanating from the button, sender will be a reference to the button.

§ There is a still shorter form that omits both parameters.

What is the UIEvent, and what is it for? Well, a touch event is generated whenever the user does something with a finger (sets it down on the screen, moves it, raises it from the screen). UIEvents are the lowest-level objects charged with communication of touch events to your app. A UIEvent is basically a timestamp (a Double) along with a collection (Set) of touch events (UITouch). The action mechanism deliberately shields you from the complexities of touch events, but by electing to receive the UIEvent, you can still deal with those complexities if you want to.

WARNING

Curiously, none of the action selector parameters provide any way to learn which control event triggered the current action selector call! Thus, for example, to distinguish a Touch Up Inside control event from a Touch Up Outside control event, their corresponding target–action pairs must specify two different action handlers; if you dispatch them to the same action handler, that handler cannot discover which control event occurred.

The Responder Chain

A responder is an object that knows how to receive UIEvents directly (see the previous section). It knows this because it is an instance of UIResponder or a UIResponder subclass. If you examine the Cocoa class hierarchy, you’ll find that just about any class that has anything to do with display on the screen is a responder. A UIView is a responder. A UIWindow is a responder. A UIViewController is a responder. Even a UIApplication is a responder. Even the app delegate is a responder!

If you look in the UIResponder class documentation, you’ll find that it implements four low-level methods for receiving touch-related UIEvents (the touch methods):

§ touchesBegan:withEvent:

§ touchesMoved:withEvent:

§ touchesEnded:withEvent:

§ touchesCancelled:withEvent:

These methods are called to notify a responder of a touch event. No matter how your code ultimately hears about a user-related touch event — indeed, even if your code never hears about a touch event (because Cocoa reacted in some automatic way to the touch, without your code’s intervention) — the touch was initially communicated to a responder through one of the touch methods.

The mechanism for this communication starts by deciding which responder the user touched. The UIView methods hitTest:withEvent: and pointInside:withEvent: are called until the correct view (the hit-test view) is located. Then UIApplication’s sendEvent: method is called, which calls UIWindow’s sendEvent:, which calls the correct touch method of the hit-test view (a responder).

The responders in your app participate in a responder chain, which essentially links them up through the view hierarchy. A UIView can sit inside another UIView, its superview, and so on until we reach the app’s UIWindow (a UIView that has no superview). The responder chain, from bottom to top, looks like this:

1. The UIView that we start with (here, the hit-test view).

2. If this UIView is a UIViewController’s view, that UIViewController.

3. The UIView’s superview.

4. Go back to step 2 and repeat! Keep repeating until we reach…

5. The UIWindow.

6. The UIApplication.

7. The UIApplication’s delegate.

Deferring Responsibility

The responder chain can be used to let a responder defer responsibility for handling a touch event. If a responder receives a touch event and can’t handle it, the event can be passed up the responder chain to look for a responder that can handle it. This can happen in two main ways:

§ The responder doesn’t implement the relevant touch method.

§ The responder implements the relevant touch method to call super.

For example, a plain vanilla UIView has no native implementation of the touch methods. Thus, by default, even if a UIView is the hit-test view, the touch event effectively falls through the UIView and travels up the responder chain, looking for someone to respond to it. In certain situations, it might make logical sense for you to defer responsibility for this touch to the main background view, or even to the UIViewController that controls it.

Here’s an example from one of my apps. The app is a game that’s a simple jigsaw puzzle: a rectangular photo is divided into smaller pieces, and the pieces are shuffled. The user’s job is to tap two pieces in succession to swap them. The background view is a UIView subclass called Board; the puzzle pieces are generic UIView objects, and are subviews of the Board. Knowledge of how a piece should respond when tapped resides in the Board, which knows the overall layout of the pieces; thus, I don’t need a puzzle piece to contain any tap detection logic. Therefore I take advantage of the responder chain to defer responsibility: the puzzle pieces don’t implement any touch methods, and a tap on a puzzle piece falls through to the Board, which does perform touch detection and handles the tap, and tells the tapped piece what to do. The user, of course, knows nothing about that: outwardly, you touch a piece and the piece responds.

Nil-Targeted Actions

A nil-targeted action is a target–action pair in which the target is nil. There is no designated target object, so the following rule is used: starting with the hit-test view (the view with which the user is interacting), Cocoa walks up the responder chain, one responder at a time, looking for an object that can respond to the action message:

§ If a responder is found that handles this message, that method is called on that responder, and that’s the end.

§ If we get all the way to the top of the responder chain without finding a responder to handle this message, the message goes unhandled (with no penalty) — in other words, nothing happens.

Suppose, for example, that we were to configure a button in code, like this:

self.button.addTarget(nil,

action: "buttonPressed:",

forControlEvents: .TouchUpInside)

That’s a nil-targeted action. So what happens when the user taps the button? First, Cocoa looks in the UIButton itself to see whether it responds to buttonPressed:. If not, it looks in the UIView that is its superview. And so on, up the responder chain. If self is the view controller that owns the view that contains the button, and if the class of this view controller does in fact implement buttonPressed:, tapping the button will cause the view controller’s buttonPressed: to be called!

It’s obvious how to construct a nil-targeted action in code: you set up a target–action pair where the target is nil, as in the preceding example. But how do you construct a nil-targeted action in a nib? The answer is: you form a connection to the First Responder proxy object (in the dock).This is what the First Responder proxy object is for! The First Responder isn’t a real object with a known class, so before you can connect an action to it, you have to define the action message within the First Responder proxy object, like this:

1. Select the First Responder proxy in the nib, and switch to the Attributes inspector.

2. You’ll see a table (probably empty) of user-defined nil-targeted First Responder actions. Click the Plus button and give the new action a signature; it must take a single parameter (so that its name will end with a colon).

3. Now you can Control-drag from a control, such as a UIButton, to the First Responder proxy to specify a nil-targeted action with the signature you specified.

Key–Value Observing

Key–value observing, or KVO, is a notification mechanism that doesn’t use the NSNotificationCenter. It allows one object to be registered directly with a second object so as to be notified when a value in the second object changes. Moreover, the second object — the observed object — doesn’t actually have to do anything; it needn’t even be conscious of the fact that this registration has taken place. When the value in the observed object changes, the registered object — the observer — is notified automatically. (Perhaps a better architectural analogy would be with the target–action mechanism; this is a target–action mechanism that works between any two objects.)

When you use KVO, the observer will be your object; you will write the code that will respond when the observer is notified of the change for which it has registered. But the observed object, the one with which you register to hear about changes, needn’t be your object at all; in fact, it often will not be. Many Cocoa objects promise to behave in a KVO compliant way, and you are invited and expected to use KVO on them. Typically, KVO is used in place of delegation or notifications.

The process of using KVO may be broken down into three stages:

Registration

To hear about a change in a value belonging to the observed object, we must be registered with the observed object. This typically involves calling the observed object’s addObserver:forKeyPath:options:context: method. (All objects derived from NSObject have this method, because it is injected into NSObject by the informal protocol NSKeyValueObserving, which is actually a set of categories on NSObject and other classes.)

Change

The change takes place in the value belonging to the observed object, and it must take place in a special way — a KVO compliant way. Typically, this means using a key–value coding compliant accessor to make the change. Setting a property passes through a key–value coding compliant accessor.

Notification

The observer is automatically notified that the value in the observed object has changed: its observeValueForKeyPath:ofObject:change:context: method, which we have implemented for exactly this purpose, is called by the runtime.

It is also necessary, sooner or later, to unregister with the observed object when we no longer want to receive this notification, by sending it removeObserver:forKeyPath: (or removeObserver:forKeyPath:context:). This is important for the same reason that unregistering for an NSNotification is important: if we don’t, the app can crash if the notification is sent to an observer that has gone out of existence. You must explicitly unregister the observer for every key path for which it is registered; you can’t use nil as the second argument to mean “all key paths.” The last possible moment to unregister is the observer’s deinit; obviously, this requires that the observer have a reference to the observed object.

But there’s more. All observers must be unregistered from an observed object before the observed object goes out of existence! If an object goes out of existence with observers still registered with it, your app will crash, with a helpful message in the console: “An instance … was deallocated while key value observers were still registered with it.”

Here’s an example from my actual code. An AVPlayerViewController is a view controller whose view displays video content. When the view first appears, there can be a nasty flash, because the view is black until the video content is ready, which may take a little time. The solution is to make the view initially invisible, until the video content is ready. Thus, we want to be notified when the video content is ready. AVPlayerViewController has a readyForDisplay property — so we want to be notified when that property becomes true. But AVPlayerViewController has no delegate, and provides no notifications. The solution is to use KVO: we register ourself with the AVPlayerViewController to hear about changes in its readyForDisplay property. Here’s the part of my code that configures and shows an AVPlayerViewController’s view:

func setUpChild() {

// ...

let av = AVPlayerViewController()

av.player = player

av.view.frame = CGRectMake(10,10,300,200)

av.view.hidden = true // looks nicer if we don't show until ready

av.addObserver(self,

forKeyPath: "readyForDisplay", options: nil, context: nil) 1

// ...

}

override func observeValueForKeyPath(keyPath: String,

ofObject object: AnyObject, change: [NSObject : AnyObject],

context: UnsafeMutablePointer<()>) { 2

if keyPath == "readyForDisplay" {

if let obj = object as? AVPlayerViewController {

dispatch_async(dispatch_get_main_queue(), {

self.finishConstructingInterface(obj)

})

}

}

}

func finishConstructingInterface (vc:AVPlayerViewController) {

if !vc.readyForDisplay {

return

}

vc.removeObserver(self, forKeyPath:"readyForDisplay") 3

vc.view.hidden = false

}

1

The AVPlayerViewController’s view starts out invisible (hidden is true). We register to hear about any change in its readyForDisplay property.

2

The AVPlayerViewController’s readyForDisplay property changes, and we hear about it because observeValueForKeyPath:... is called. We make sure this is the right notification; if it is, we proceed to finish constructing the interface. Note that the observed object (the AVPlayerViewController) arrives as the object parameter; this not only helps us identify the notification, but also allows us to communicate with that object. There are no guarantees about the thread on which observeValueForKeyPath:... will be called, so we step out to the main thread before doing anything that would affect the interface.

3

After one final check to make sure that readyForDisplay actually changed from false to true, we unregister — we only need to hear about this change this once — and proceed to make the view visible (hidden is false).

When we registered ourself as observer, we didn’t supply any options: argument. One of the things this argument lets us do (NSKeyValueObservingOptions, a bitmask) is ask for the new value of the changed property to be sent to us in the change: dictionary. Thus, we can rewrite our code so as to move the check for whether readyForDisplay is now true into our implementation of observeValueForKeyPath.... We now register like this:

av.addObserver(

self, forKeyPath: "readyForDisplay", options: .New, context: nil)

And here’s the rest of the code (see Chapter 5 on the extended conditional binding syntax):

override func observeValueForKeyPath(keyPath: String,

ofObject object: AnyObject, change: [NSObject : AnyObject],

context: UnsafeMutablePointer<()>) {

if keyPath == "readyForDisplay",

let obj = object as? AVPlayerViewController,

let ok = change[NSKeyValueChangeNewKey] as? Bool where ok {

dispatch_async(dispatch_get_main_queue(), {

self.finishConstructingInterface(obj)

})

}

}

func finishConstructingInterface (vc:AVPlayerViewController) {

vc.removeObserver(self, forKeyPath:"readyForDisplay")

vc.view.hidden = false

}

You’re probably wondering about the context: parameter in addObserver:... and observeValueForKeyPath:.... On the whole, I recommend against using this parameter, but I’ll tell you about it anyway. It is said to represent “arbitrary data” that is handed intoaddObserver:... and retrieved in observeValueForKeyPath:.... You have to be careful with its value, however, because it is typed as UnsafeMutablePointer<Void>. This means that its memory is not managed while the runtime has hold of it; you must manage its memory by keeping a persistent reference to the value elsewhere. The usual approach is to use a global variable (a variable declared at the top level of a file); to prevent it from being too global, you can declare it private, like this:

private var con = "ObserveValue"

When you call addObserver:..., you pass the address of this variable, &con, as the context: argument. When you are notified in observeValueForKeyPath:..., you can use the context: parameter as an identifier by comparing it to &con:

override func observeValueForKeyPath(keyPath: String,

ofObject object: AnyObject, change: [NSObject : AnyObject],

context: UnsafeMutablePointer<Void>) {

if context != &con {

return // wrong notification

}

// ...

}

In that code, the value stored in the global variable is irrelevant; we are using its address as an identifier. If you want to use the value stored in the global variable, coerce the UnsafeMutablePointer to another UnsafeMutablePointer specified as the underlying type. Now you can access the underlying value as the UnsafeMutablePointer’s memory property. In our example, con is a String:

override func observeValueForKeyPath(keyPath: String,

ofObject object: AnyObject, change: [NSObject : AnyObject],

context: UnsafeMutablePointer<Void>) {

let c = UnsafeMutablePointer<String>(context)

let s = c.memory // "ObserveValue"

// ...

}

Key–value observing is a deep mechanism; consult Apple’s Key-Value Observing Guide for full information. (For example, it is possible to observe a mutable NSArray, but the mechanism is more elaborate than I have described here.) KVO also has some unfortunate shortcomings. For one thing, it’s a pity that all notifications arrive by calling the same bottleneck method, observeValueForKeyPath:.... And keeping track of who’s observing whom, and making sure both observer and observed have appropriate lifetimes and that unregistration takes place in a timely fashion, can be tricky. But in general, KVO is useful for keeping values coordinated in different objects; and, as I’ve already said, certain parts of Cocoa will expect you to use it.

TIP

Both the observed and the observer in KVO must derive from NSObject. Moreover, if the property to be observed is declared in Swift, it must be marked dynamic — otherwise, KVO won’t work. (The reason is that KVO works by swizzling the accessor methods; Cocoa needs to be able to reach right in and change your object’s code, and it can’t do that unless the property isdynamic.)

Swamped by Events

Your code runs only because Cocoa sends an event and you had previously set up a method ready to receive it. Cocoa has the potential to send lots of events, telling you what the user has done, informing you of each stage in the lifetime of your app and its objects, asking for your input on how to proceed. To receive the events that you need to hear about, your code is peppered with methods that are entry points — methods that you have written with just the right name and in just the right class so that they can be called by Cocoa through events. In fact, it is easy to imagine that in many cases your code for a class will consist almost entirely of entry points.

Arranging all those entry points is one of your primary challenges as an iOS programmer. You know what you want to do, but you don’t get to “just do it.” You have to divide up your app’s functionality and allocate it in accordance with when and how Cocoa is going to call into your code. Before you’ve written a single line of your own code, the skeleton structure of a class is likely to have been largely mapped out for you by the need to be prepared to receive the events that Cocoa is going to want to send you.

Suppose, for example, that your iPhone app presents an interface consisting of a table view. (This is in fact an extremely probable scenario.) You’re likely to have a corresponding UITableViewController subclass; UITableViewController is a built-in UIViewController subclass, and an instance of your UITableViewController subclass will own and control the table view, plus you’ll probably use this same class as the table view’s data source and delegate. In this single class, then, you’re likely to want to implement at a minimum the following methods:

initWithCoder: or initWithNibName:bundle:

UIViewController lifetime method, where you perform instance initializations.

viewDidLoad

UIViewController lifetime method, where you perform view-related initializations.

viewDidAppear:

UIViewController lifetime method, where you set up states that need to apply only while your view is onscreen. For example, if you’re going to register for a notification or set up a timer, this is a likely place to do it.

viewDidDisappear:

UIViewController lifetime method, where you reverse what you did in viewDidAppear:. For example, this would be a likely place to unregister for a notification or invalidate a repeating timer that you set up in viewDidAppear:.

supportedInterfaceOrientations

UIViewController query method, where you specify what device orientations are allowed for this view controller’s main view.

numberOfSectionsInTableView:
tableView:numberOfRowsInSection:
tableView:cellForRowAtIndexPath:

UITableView data source query methods, where you specify the contents of the table.

tableView:didSelectRowAtIndexPath:

UITableView delegate user action method, where you respond when the user taps a row of the table.

deinit

Swift class instance lifetime method, where you perform end-of-life cleanup.

Suppose, further, that you did in fact use viewDidAppear: to register for a notification and to set up a timer. Then that notification has a selector (unless you used a block), and the timer has a selector; you must therefore also implement the methods specified by those selectors.

We already have, then, about a dozen methods whose presence is effectively a matter of boilerplate. These are not your methods; you are never going to call them. They are Cocoa’s methods, which you have placed here so that each can be called at the appropriate moment in the life story of your app.

The logic of a program laid out in this fashion is by no means easy to understand! I’m not criticizing Cocoa here — indeed, it’s hard to imagine how else an application framework could work — but, purely as an objective matter of fact, the result is that a Cocoa program, even your own program, even while you’re developing it, is hard to read, because it consists of numerous disconnected entry points, each with its own meaning, each called at its own set moment which is not in any way obvious from looking at the program. To understand what our hypothetical class does, you have to know already such things as when viewDidAppear: is called and how it is typically used; otherwise, you don’t even know where to look to find the program’s logic and behavior, let alone how to interpret what you see when you do look there. And this difficulty is greatly compounded when you try to read someone else’s code (this is one reason why, as I mentioned in Chapter 8, sample code is not all that helpful to a beginner).

Looking at the code of an iOS program — even your own code — your eyes can easily glaze over at the sight of all these methods called automatically by Cocoa under various circumstances. To be sure, experience will teach you about such things as the overridden UIViewController methods and the table view delegate and data source methods. On the other hand, no amount of experience will tell you that a certain method is called as a button’s action or through a notification. Comments really help, and I strongly advise you, as you develop any iOS app, to comment every method, quite heavily if need be, saying what that method does and under what circumstances you expect it to be called — especially if it is an entry point, where it is Cocoa itself that will do the calling.

Perhaps the most common kind of mistake in writing a Cocoa app is not that there’s a bug in your code itself, but that you’ve put the code in the wrong place. Your code isn’t running, or it’s running at the wrong time, or the pieces are running in the wrong order. I see questions about this sort of thing all the time on the various online user forums (these are all actual examples that appeared over the course of just two days):

§ There’s a delay between the time when my view appears and when my button takes on its correct title.

That’s because you put the code that sets the button’s title in viewDidAppear:. That’s too late; your code needs to run earlier, perhaps in viewWillAppear:.

§ My subviews are positioned in code and they’re turning out all wrong.

That’s because you put the code that positions your subviews in viewDidLoad. That’s too early; your code needs to run later, when your view’s dimensions have been determined.

§ My view is rotating even though my view controller’s supportedInterfaceOrientations says not to.

That’s because you implemented supportedInterfaceOrientations in the wrong class; it needs to be implemented in the UINavigationController that contains your view controller (or by using the delegate’s navigationControllerSupportedInterfaceOrientations, as I described earlier in this chapter).

§ I set up an action connection for Value Changed on a text field, but my code isn’t being called when the user edits.

That’s because you connected the wrong action; a text field emits Editing Changed, not Value Changed.

Adding to your challenges is that fact that you can’t really know precisely when an entry point will be called. The documentation may give you a general sense, but in most cases there are no guarantees about when events will arrive and in what order. What you think is going to happen, and even what the documentation leads you to believe is going to happen, might not be quite what really does happen. Your own code can trigger unintended events. The documentation might not make it clear just when a notification will be sent. There could even be a bug in Cocoa such that events are called in a way that seems to contradict the documentation. And you have no access to the Cocoa source code, so you can’t work out the underlying details. Therefore I also recommend that as you develop your app, you instrument your code heavily with caveman debugging (println and NSLog; see Chapter 9). As you test your code, keep an eye on the console output and check whether the messages make sense. You may be surprised at what you discover.

Delayed Performance

Your code is executed in response to some event; but your code in turn may trigger a new event or chain of events. Sometimes this causes bad things to happen: there might be a crash, or Cocoa might appear not to have done what you said to do. To solve this problem, sometimes you just need to step outside Cocoa’s own chain of events for a moment and wait for everything to settle down before proceeding.

The technique for doing this is called delayed performance. You tell Cocoa to do something, not right this moment, but in a little while, when things have settled down. Perhaps you need only a very short delay, possibly even as short as zero seconds, just to let Cocoa finish doing something, such as laying out the interface. Technically, you’re allowing the current run loop to finish, completing and unwinding the entire current method call stack, before proceeding further with your own code.

When you program iOS, you’re likely to be using delayed performance a lot more than you might expect. With experience, you’ll develop a kind of sixth sense for when delayed performance might be the solution to your difficulties.

The main way to get delayed performance in iOS programming is by calling dispatch_after. It takes a block (a function) stating what should happen after the specified time has passed. Calling dispatch_after is a bit elaborate, though, especially in Swift where there’s a lot of casting to do; so I’ve written a global utility function that simplifies things and calls dispatch_after for me:

func delay(delay:Double, closure:()->()) {

dispatch_after(

dispatch_time(

DISPATCH_TIME_NOW,

Int64(delay * Double(NSEC_PER_SEC))

),

dispatch_get_main_queue(), closure)

}

That utility function is so important that I routinely paste it at the top level of the AppDelegate class file in every app I write. It’s going to come in handy, I know! To use it, I call delay with a delay time (usually a very small number of seconds such as 0.1) and an anonymous function saying what to do after the delay. Note that what you propose to do in this anonymous function will be done later on; you’re deliberately breaking out of your own code’s line-by-line sequence of execution. So a delayed performance call will be the last call in its own surrounding function, and cannot return any value.

In this actual example from one of my own apps, the user has tapped a row of a table, and my code responds by creating and showing a new view controller:

override func tableView(tableView: UITableView,

didSelectRowAtIndexPath indexPath: NSIndexPath) {

let t = TracksViewController(

mediaItemCollection: self.albums[indexPath.row])

self.navigationController!.pushViewController(

t, animated: true)

}

Unfortunately, the innocent-looking call to my TracksViewController initializer init(mediaItemCollection:) can take a moment to complete, so the app comes to a stop with the table row highlighted — very briefly, but just long enough to startle the user. To cover this delay with a sense of activity, I’ve rigged my UITableViewCell subclass to show a spinning activity indicator when it’s selected:

override func setSelected(selected: Bool, animated: Bool) {

if selected {

self.activityIndicator.startAnimating()

} else {

self.activityIndicator.stopAnimating()

}

super.setSelected(selected, animated: animated)

}

But there’s a problem: the spinning activity indicator never appears and never spins. The reason is that the events are stumbling over one another here. UITableViewCell’s setSelected:animated: isn’t called until the UITableView delegate methodtableView:didSelectRowAtIndexPath: has finished. But the delay we’re trying to paper over is during tableView:didSelectRowAtIndexPath:; the whole problem is that it doesn’t finish fast enough.

Delayed performance to the rescue! I’ll rewrite tableView:didSelectRowAtIndexPath: so that it finishes immediately — thus triggering setSelected:animated: immediately and causing the activity indicator to appear and spin — and I’ll use delayed performance to callinit(mediaItemCollection:) later on, when the interface has ironed itself out:

override func tableView(tableView: UITableView,

didSelectRowAtIndexPath indexPath: NSIndexPath) {

delay(0.1) { // let spinner start spinning

let t = TracksViewController(

mediaItemCollection: self.albums[indexPath.row])

self.navigationController!.pushViewController(

t, animated: true)

}

}