Hour 13. Building on the Foundation


What You’ll Learn in This Hour

Image Exploring the frameworks that extend Objective-C

Image Understanding Foundation policies and paradigms

Image Working with mutable classes

Image Using class clusters

Image Handling notifications


Exploring the Foundation Framework

This book is about the Objective-C language; the Cocoa and Cocoa Touch frameworks are outside the scope of the book. However, the Foundation framework is relevant. The earliest guide to Objective-C, Object Oriented Programming: An Evolutionary Approach by Brad J. Cox (who codeveloped the language with Tom Love) was published in 1986. It describes Objective-C before the NeXT extensions and before the later extensions at Apple that culminated in OS X and iOS. The objects and methods listed in this book for the most part are still part of the language today. They were organized into collections in 1986; today they are organized into frameworks, a somewhat different structure, but still an organizing tool for objects.

These classes and methods are part of the language itself: Today, they are part of the Foundation framework (sometimes referred to simply as Foundation). They include the root class, NSObject. The performSelector method discussed at length in Hour 12, “Routing Messages with Selectors,” for example, is a method of NSObject in the Cox book. Today, it has moved from NSObject itself to the NSObject protocol, but that is a relatively minor change.

The major Cocoa and Cocoa Touch frameworks are AppKit (OS X) and UIKit (iOS). These differ from the Foundation framework in that Foundation has nothing to do with the user interface. Thus, windows, views, and controls are not found anywhere in Foundation. There are a number of other Cocoa frameworks such as Core Data, Address Book, WebKit (only public in OS X), iAd (iOS only), and Preference Panes (OS X only). These are also beyond the scope of this book.

The complete Foundation Framework Reference is available on developer.apple.com as well as in Xcode (it is 2,000 pages long). This hour and others that follow provide a high-level road map and introduction.

There is a companion to the Foundation framework: the Core Foundation framework. They have similar structures and functionality, but Foundation is written in Objective-C, whereas Core Foundation is written in C. This was done in part to support the Carbon development environment that was a critical part of the transition from the C and C++ world of the Macintosh operating system to the Objective-C world of OS X. (By way of comparison, the Core Foundation Framework Reference is a mere 800 pages long.)

Foundation Classes

Foundation contains the classes that you use and subclass in your apps. There are two root classes along with a variety of other classes that are divided into groups.

Root Classes

NSObject has been referred to as the root class for all other classes. In fact, it is one of two root classes—the other is NSProxy, which is used with distributed objects. As the name suggests, it stands in for an object that may be distant or even may not be created yet. NSProxy is a relatively recent addition to the world of Objective-C, and its addition caused a restructuring that has been alluded to previously.

The NSObject protocol contains methods that formerly were part of the NSObject class itself. By pulling a number of them out into the NSObject protocol, all the root objects (that is, both of them) can share the functionality of the protocol.


Turning Part of a Class into a Protocol

This restructuring is something you might want to do in similar circumstances. If you were starting from scratch, you might design an abstract object (perhaps RootClass) and subclass it into NSProxy and NSObject. In your own development, you can easily come across a situation in which you want to insert a new abstract object so that two existing objects can subclass it and share its functionality. That can entail quite a bit of restructuring, so using the technique of taking the common methods out into a protocol adopted by your original object, and also by the new object, can be less work. It also means that if your original object adopts the new protocol, you can leave all of its code intact with perhaps a slight adjustment to the protocol declarations in the source code.

The NSObject root class and its proxy implement methods in the following areas. Note that this is not a complete list of the methods in each area; it is designed to give you a general idea of what is included.

Image Allocation, initialization, and duplication—You have already seen some of the commonly used methods in this area, such as alloc and init.

Image Introspection and comparison—You have seen respondsToSelector: and instancesRespondToSelector: as well as description in other hours. Additional methods in this area include isEqual: for testing two objects as well as the introspection methods class and superclass, which return the appropriate values as class objects (not strings).

Image Encoding and decoding—The methods in this area are used in archiving and unarchiving objects—converting them from objects in memory to byte streams that can be transmitted or written to files (and vice versa).

Image Message forwarding—This allows an object to forward a message it has received to another object.

Image Message dispatch—This includes the performSelector methods described in Hour 12.

Image Object retention and disposal—Methods such as retain, release, autorelease, retainCount, and dealloc let you manage memory for your objects.


GO TO Image Hour 16, “Managing Memory and Runtime Objects,” p. 221, for more on this topic as well as a discussion of Automatic Reference Counting (ARC), which eliminates the need for much manual memory management in object retention and disposal.

Other Classes

Beyond the root classes and their shared protocol, the other Foundation classes are divided into a number of groups. They provide object-oriented support for common programming tasks. The groups are the following:

Image Value objects—These include numbers, dates, and general data types.

Image XML support—These methods help you parse XML documents.

Image Strings—These methods include string classes themselves as well as support classes such as NSFormatter.

Image Collections—These include arrays, dictionaries, and sets.

GO TO Image Hour 15, “Organizing Data with Collections,” p. 205, for more on collections.

Image Predicates—These methods help you construct predicates for use in selecting data.

Image Operating system services—Here, you find everything from spell checking to timers and NSError.

Image File system—These routines manage files, metadata, and streams.

Image URL—These are the methods to connect to and download files by URL. They also include methods to handle cookies.

Image Interprocess communication—IPC has been a built-in component of Objective-C and Cocoa for many years. These methods implement pipes and ports among others.

Image Locking/threading—These methods let you manage multiple threads in your apps.

Image Notifications—The notification methods let you use the Objective-C messaging structure to keep track of events as they occur.

Image Objective-C language services—These include methods such as NSMethodSignature, which was discussed in Hour 12 in the context of invocations.

Image Scripting—These are the methods to handle Apple events and script commands. They are implemented only on OS X.

Image Distributed objects—These methods are also only implemented on OS X. They are supported by NSProxy, which is what led to the restructuring of NSObject.

Foundation Paradigms and Policies

The common underpinnings of Foundation include implementation of policies and paradigms that are implemented across the other frameworks and in the code that you write. There are four sections of these paradigms and policies:

Image Mutability

Image Class clusters

Image Notifications

Image Garbage collection

GO TO Image Hour 16, “Managing Memory and Runtime Objects,” p. 221, for a discussion of garbage collection.

Mutability

Many Foundation classes, such as NSArray, NSSet, NSString, and NSData, have mutable and immutable variants. Typically, the mutable variant is a subclass of the immutable one; the mutable subclass is identified by its name. For example, NSMutableArray is the mutable variant of NSArray. As you can imagine, this can make it possible for the compiler and runtime to optimize performance for the immutable variants.

If your changes to a mutable class are isolated to one or two methods (and that is often a good design), that can enable you to take advantage of the efficiencies of working with immutable variants. You can work with an immutable array or other class and, when you need to modify it, use mutableCopy to make a mutable copy, modify it, and then use copy to turn it back into an immutable object. (That is the default behavior for copy.) You can then continue with the immutable copy.


Tip

Whether this type of switching between mutable and immutable variants is worthwhile or not depends on how much modifying you need to carry out compared with how much time it takes to copy the object in question.


Class Clusters

Foundation makes use of class clusters that group hidden subclasses behind an abstract superclass with which you interact. The most commonly cited example of a class cluster is NSNumber. There are hidden subclasses of the abstract NSNumber class that are used for ints, longlongs, chars, and so forth. The init methods of the abstract superclass dispatch the appropriate factory methods to create the appropriate hidden subclass as in the following code:

NSNumber *myInteger = [NSNumber numberWithInt: 1234];

Inside the abstract superclass NSNumber, numberWithInt creates a specific and hidden subclass that is an int. You only see an NSNumber, but it hides the various subclasses from you.


Tip

You can use this design pattern in your own code. It is an excellent way of implementing a variety of subclasses without revealing that they are separate subclasses.


Notifications

Notifications provide a broadcast type of communication. Observers register to watch a certain event, and objects within your app post notifications. This is handled by a notification center that is part of each process.

Notifications are a very efficient low-level form of communicating information throughout your app. In many cases, they are an alternative to polling inside a loop to test whether or not something has happened. You just register to receive notifications about the event in which you are interested, and, assuming that you properly broadcast a notification when the event occurs, you find out that the event has occurred. There is no need for a polling loop to repeatedly check on what has or has not happened.

Notifications are subclasses of NSNotification. There are three basic values, and you can add others if you need them. However, the basic NSNotification structure is simple and very efficient.

Every notification has these three values:

Image name—This should be a unique name within the notifications for your app. Observers need to know it so that they can register for the type of notifications in which they are interested. This is an NSString.

Image object—Typically, this is the object that posts the notification, but it need not be. It can even be nil. This is an id.

Image userInfo—This is a dictionary containing data relevant to the notification. It is up to you to define it and to let your observers know what is in it. This is an NSDictionary.

It is important to note that the notification center for a process is the clearinghouse for notifications. Your process does not need to track observers. You just post notifications as necessary, and observers will receive them. You get the notification center for your process with the following snippet of code:

[NSNotificationCenter defaultCenter];

This snippet typically is used as part of a line of code that carries out a notification task, as you see in the following sections.

Posting a Notification

To create a new notification, you can use any of the two NSNotification class methods:

+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject
+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject
    userInfo:(NSDictionary *)userInfo

Your choice between them depends on whether you want simply to pass on a notification that something has happened (the first version) or a notification along with some relevant data (the second version) with the userInfo dictionary.

More commonly, you use NSNotificationCenter methods to create and post notifications in one step. Here are the three variations:

– (void)postNotification:(NSNotification *)notification
– (void)postNotificationName:(NSString *)notificationName
    object:(id)notificationSender
– (void)postNotificationName:(NSString *)notificationName
    object:(id)notificationSender userInfo:(NSDictionary *)userInfo

You need the notification center to use these methods, so a typical use of the first one might be:

[[NSNotificationCenter defaultCenter]
  postNotificationName:(NSString *)notificationName];

Registering to Receive Notifications

You register to receive specific notifications (that is, to become an observer of the notification) with one of these NSNotificationCenter methods.

This is the simplest way to add an observer. You specify the object to be notified, as well as the selector that is sent to that object. You further specify the name of the notification and, optionally, the sender of the notification. Either or both of notificationName and notificationSender can be nil; in those cases, notifications are delivered regardless of name and/or sender.

– (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector
    name:(NSString *)notificationName object:(id)notificationSender

A typical example of registering to receive a notification would be:

[[NSNotificationCenter defaultCenter]
  addObserver: myObserver selector: (SEL)mynotificationAction
  name: nil notificationSender: nil];

GO TO Image Hour 20, “Working with Blocks,” p. 259, for more information on blocks.

Instead of using a selector, you can specify a queue and a block to add to it. The block takes one argument, which is the notification.

– (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue
 *)queue
    usingBlock:(void (^)(NSNotification *))block

Removing Observers

When you no longer want to receive notifications, just remove the appropriate observer with one of these NSNotificationCenter methods:

– (void)removeObserver:(id)notificationObserver
– (void)removeObserver:(id)notificationObserver name:
    (NSString *)notificationName object:(id)notificationSender

A typical use would be:

[[NSNotificationCenter defaultCenter]
  removeObserver: myObserver];

Summary

This hour has shown you the parts of the Objective-C language that are implemented in the Foundation framework. They include NSObject (both the class and the protocol) as well as key functionalities, such as shared paradigms and policies. You have also seen key components of Foundation such as class clusters and their hidden subclasses as well as notifications.

Q&A

Q. What do notifications accomplish?

A. They let you send messages to observers via a dispatch center. You post messages to the dispatch center, and it posts to the observers. You do not need a direct communication link to the observers.

Q. What is the purpose of class clusters?

A. These are related classes that frequently share a common abstract superclass. Developers use the methods of the abstract superclass, but in reality they are often manipulating the hidden internal subclasses. The abstract class’s initWith methods frequently take care of creating the specific subclasses.

Workshop

Quiz

1. How many notification centers are there for each app?

2. What is the purpose of mutable and immutable classes?

Quiz Answers

1. There is one notification center for each app.

2. They can let you create optimized code for objects that will not be modified.

Activities

Explore the sample code for Core Recipes (OS X) and Core Data Books (iOS) to see notifications in action. Look at DocInteraction (iOS) to see how to receive process notifications when the files in a folder change.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.197.251