The Jungle, Part 3: Flipping and Tab Bars


In previous tutorials we’ve been using some basic UIKit elements on standard views. Today, we’re going to add a tab bar to our application and wire it up; it’ll pave the way for some more compelling future expansions. Tab bars are more involved than the regular views we’ve been using; in additional to simply setting and accessing properties, we also have to contend with a specific controller and design pattern, as well as delegates. Let’s get started.

Tab Bar Controllers

In most cases, tab bars are used with UITabBarController. You may use an independent tab bar if you’re using it to display the same information in the same view, just sorted differently, for example. However, if you plan on swapping views around, you should use the controller because it manages the swapping mechanism and paradigms for you.

According to Apple’s documentation, “The UITabBarController class implements a specialized view controller that manages a radio-style selection interface.…[Y]ou use instances of it as-is to present an interface that allows the user to choose between different modes of operation. This tab bar interface displays tabs at the bottom of the window for selecting between the different modes and for displaying the views for that mode.” Tab bars are prevalent in many of the standard iOS apps, including Clock and Music.

Rather than accessing the tab bar itself (Apple claims that “You should never access the tab bar view of a tab bar controller directly”), you should pass the tab bar controller an array of UIViewControllers (or subclasses of it) to a property called viewControllers. The ordering in the array determines the order of the tabs. Alternatively, you can configure the tabs’ order, title and icon in Interface Builder. When a tab is selected, the controller will load the root view controller for the corresponding tab in the main content view. This means that if you’ve drilled into a navigation stack (which we will be covering in a future post), you will be returned back to the top of the stack, even if you tap the tab you’re currently on. By default the state of the view is not saved; however, you can do initial configuration in your own controllers to do so. Any class can become the delegate of the tab bar and receive notifications about changes. As per the nature of delegation, this is completely optional; proper configuration in Interface Builder means that the view swapping will work fine without having to create a delegate.

Getting Started

Today we’ll be creating a second view controller to have something to switch to, and then we’ll create a tab bar controller and implement the switching. The process is really intuitive once you know where to begin—so let’s begin!

Begin by creating a New File in Xcode. Make sure UIViewController subclass is selected in the Template pane and click Next.

New UIViewController Subclass File

The Class name should be FlipViewController. It should be a Subclass of UIViewController, not be targeted for iPad, and have a XIB for the user interface. Click Next, and then Create (unless you want to change the file save location or the group the new files get placed under—go ahead). You’ll get three new files—FlipViewController.h, FlipViewController.m, and FlipViewController.xib. Here, we’ll create a very simple view that implements a flip-over view like you might see in the Weather or Stocks app.

Start by creating two UIViews in the header, making sure to declare them as IBOutlets and calling them frontView and backView. In the XIB, drag out two UIViews from the Library. Connect the views—Control drag from the File’s Owner (the first icon on the strip to the left) down to the views and make the connections as you’re used to. In the view you’ve designated to be the front, choose a dark color for the Background and then drag out a UIButton. In the Attributes Inspector, next to Type, select Info Light to get you the little “i” button that you’ve seen around iOS. Align that with the bottom right corner of the view. Also in each view, add a label with “Front view” and “Back view”, just for reference. In your back view, add a regular UIButton in the upper left corner with the text “Done”. This follows the standard UI design pattern—if you’re using an info button to go to another view, the info button should be in the lower-right corner; a Done button to return sometimes may be in a nav bar (which we’ll cover in a later post), but is usually in the upper-left corner.

Now connect the actions. The method to go to the back view should be called flipToBack: and take a sender. The method to go back should be called flipToFront: and also take a sender. Of course, make sure the methods are defined in the header, save both the header and the XIB, and go to the .m file. Synthesize the frontView and backView. Add the following line to viewDidLoad after the existing code:

[self.view addSubview:self.frontView];

This will make the frontView visible. Next we’ll implement the flipping methods:

- (IBAction)flipToBack:(id)sender {
	[UIView transitionFromView:self.frontView toView:self.backView
			  duration:1.0 
			   options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromRight)
		        completion:NULL];
}

- (IBAction)flipToFront:(id)sender {
	[UIView transitionFromView:self.backView toView:self.frontView
			  duration:1.0 
			   options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromLeft)
			completion:NULL];
}

These methods are rather similar. We’re calling new UIView animation methods introduced with iOS 4 that replaced a more verbose and complicated system from before; these methods also take advantage of blocks which were also new with iOS 4 and, again, will be covered in the future. Here, we’re asking it to transition from one view to another. It’ll draw one view, and then animate in the other based on the options you pass in. The duration is the length of the time you want the animation to take. The options are a list of options (at the end of the page) you can pass in; you can combine them any way you want (barring conflicting options) using the bitwise OR operator ( | ) and enclosing the group in parentheses. Here, we’re telling the animation to use a smooth, natural ease-in and then ease-out at the end. Other options include a linear path, or just ease-in or just ease-out. Finally, you can pass a block in when the animation completes; we’re not going to do anything here for the moment. Our view controller is done—so let’s build our tab bar controller.

Creating the Tab Bar Controller

Open AppDelegate.h and add a tab bar controller property:

@property (nonatomic, retain) UITabBarController *tabBarController;

Synthesize the property. In the implementation, import FlipViewController.h and then release tabBarController in the dealloc method. Then create the tab bar controller:

RootViewController *rootViewController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
rootViewController.title = @"Root View Controller";
FlipViewController *flipViewController = [[FlipViewController alloc] initWithNibName:@"FlipViewController" bundle:nil];
flipViewController.title = @"Flip View Controller";
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:rootViewController, flipViewController, nil];
self.window.rootViewController = self.tabBarController;

First we create the view controllers and set their title. The title of the view controllers is the title that the tab bar displays. We then create a tab bar controller and set the view controllers as an array. You then set the root view controller as before.

If you run the program now, you’ll get a working app with a tab bar at the bottom. Switch between the tabs and go to the Flip View Controller—and you’ll realize the issue we have. The tab bar is in fact obscuring the flip button. The solution is rather simple—go to FlipViewController.xib.

Simulated Tab Bar & Moved Button

Select the front view and move up the Info button. Select the front view itself and go to the Attributes Inspector. Under Simulated Metrics, select Tab Bar from the list next to Bottom Bar. Using that as a guide, position the info button. Build and run again. The flip view will work as you’ve seen in other Apple apps.

Apple’s Progression

In iOS 5, Apple’s recommended way to create controllers is through code in the App Delegate. In previous versions you’d have started with a MainWindow.xib which you can configure in Interface Builder. I feel that because from now on all project templates will feature this new code, it is important to get to know it.

You can download the current iteration of the file here.

Extension: Cocoa Naming Conventions


The Cocoa framework and applications that use Cocoa (Touch) follow a fixed set of naming conventions that make the programs easier to read, use, and understand.

General Principles

  • Keep your code brief, but never at the expense of clarity. You’ll often see long method names in Cocoa—some programmers will complain about them, but the truth is that they make the code that much more understandable. And with Xcode’s code completion, you really don’t have to worry about all that extra typing. As an example, consider the method name removeObjectAtIndex:. That’s a very clear method name—you’re removing an object, and the argument takes an index. However, the method remove: is significantly less clear. Are you passing in an object to be removed, or an index to be removed? Or something else? The method never specifies.
  • Don’t add redundancy to names. Prefixes such as “my” or suffixes such as “object” are (almost, in the case of the latter) always unnecessary—it is obvious that it’s your variable, or that (in many cases) it’s an object.
  • 95% of the time, don’t abbreviate unless it is a well-known technical term, such as PDF or URL. Abbreviations are often not as obvious as you think they are, especially for developers from other lingual backgrounds.
  • Avoid noun/adjective-verb dualities. For instance, you may encounter a method called displayText. Does that method perform the action of displaying the text, or does it signify the text that is displayed (versus some private identifier text)? The developer has no way of knowing.
  • Consistency is important. Don’t have a count method in one class and a size method in another. Classes which have methods of the same name should do the same thing with those methods.
  • Prefixes are encouraged in Cocoa, and are used throughout Cocoa itself. Foundation and many desktop Cocoa classes begin with NS; UIKit classes begin with UI. Many developers who publish source code will prefix things with their initials, or some initialism of their company. Prefixes are especially important in determining who wrote the code, especially with generic names, such as the String class (which exists in languages such as Java).
  • Class names should have a noun involved. Other names, especially enumerated types/state representations, should have some resemblance to the class name. For example, UITableViewCell is a class, and you can specify a style using constants such as UITableViewCellStyleDefault or UITableViewCellStyleSubtitle. These constants are long, but make it clear that they work with UITableViewCell and involve its style. If you just had Default and Subtitle, they’re very ambiguous, could be used by other classes (which could lead to interesting mix-ups and collisions), and are not at all clear about what they’re referring to.
  • Categories are usually expressed as className+categoryName, such as the fictitious NSString+HTMLFormatting. Note there the “HTML” abbreviation, which is completely acceptable because HTML is widely understood.
  • Delegate and Data Source protocols will have the descriptor in the name—note UITableViewDelegate and UITableViewDataSource.
  • Other protocol names usually take a verb form of the noun they modify. For example, the NSCoding protocol works with NSCoder and NSDecoder classes.
  • Method Names

  • Method names usually begin with a lowercase letter, and each subsequent “word” in the name has its initial letter capitalized. Avoid abbreviations that are not clear. Most methods should not begin with a prefix, but you may use a prefix to denote a private method. You may also use a leading underscore (no, Apple does not reserve this method, although any Apple method with a leading underscore is supposed to be private).
  • Methods that perform an action should start with a verb. Auxiliary verbs such as “do” are not necessary and add nothing to the method except extra typing. According to the documentation, “never use adverbs or adjectives before the verb.”
  • If the method returns an attribute, the method should have the same name as the attribute, without any other modifiers, such as “calculate” or “get”. This is the naming convention that getters for properties follow.
  • Name all arguments, and make the name describe the argument. See the remove: example above.
  • Only use “and” to link two parts of a method that do different thing. For example, do not write getValue:andData:, but a method name like getValue:andDelete: is correct because it is doing two things—reading in a value and deleting (potentially) something else.
  • Verbs should not be made into adjectives. performsCalculation is preferred to calculationPerformed
  • Delegate & Data Source Methods

  • The first argument should be the object that is making the delegate or data source call. In certain cases, a class such as a view controller may be managing more than one object, such as a table view. In that case, the view controller can check to see which table view is calling the method.
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        if (tableView == tableView1)
            // return 1;
        else if (tableView == tableView2)
            // return 2;
        else
            // return something else
    }

    You’re comparing instances here, so you can use the == operator. They’ll both point to the same thing, because you’re just passing pointers around—in memory, there is only one instance of tableView1 and tableView2.

  • Delegate methods often use “did” and “will” to notify the delegate that something is about to happen, or has happened. This allows the delegate to prepare or setup some data, or to clean up after an operation. The terms provide a sense of time.
  • Methods that ask a delegate for permission, such as shouldDeleteObjectAtIndex:, should use the term “should”.
  • Miscellaneous

  • Use enumerated types, often with a typedef, to declare constants, rather than plain integers. This gives a name to the numbers, and makes it much more meaningful later. UITableViewCellStyleDefault is a lot more meaningful than simply 0.
  • Preprocessor constants are usually in all-caps, with an underscore separating the words, LIKE_THIS. Preprocessor macros maybe be named either like this, or as a standard method name; the former is preferred. Preprocessor macros defined by the compiler have leading and trailing double underscores, such as __LINE__.
  • Exceptions are named as Prefix+UniqueName+Exception, such as NSIllegalSelectorException or NSRangeException.
  • A much more in-depth look at naming conventions, along with more examples and more rules is available from Apple’s developer documentation:

    Coding Guidelines for Cocoa.

Mutable vs. Immutable Strings


As promised, some more interesting topics are on the way. Today, I stumbled across an interesting question over at StackOverflow:

Usage of NSString and NSMutableString objects in Objective C

The primary point of confusion is the exact role of NSMutableString, and how it differs from NSString. It’s a topic well worth looking into, so let’s dive right in.

Inheritance

Conveniently, NSMutableString is a subclass of NSString, which makes things a lot easier. In Java for example, the String class is barely related to the StringBuilder class (functionally similar to NSMutableString), which means that there could be constant conversions between the two classes, which is neither efficient nor convenient to code. Inheritance negates this issue.

Many methods in the Foundation and UIKit frameworks take or return NSStrings. If you had a mutable string that you meticulously constructed, you would not have to convert it to an NSString—you could just pass it right in, and reuse it as necessary. You don’t even have to cast it to an NSString. Not only is this convenient to code, it’s also more efficient. You don’t have to copy the mutable string and turn it into a regular string, which is certainly not all the efficient (relatively speaking, it could take thousands of nanoseconds, rather than the tens of nanoseconds it would take to pass a pointer). Speaking of memory, why are two separate classes needed anyway?

In-Memory

Okay, so that segue might not have made much sense. But it actually all has to do with how the strings are represented in memory. An NSString is a static block of memory that has been allocated wherever there was free space at the time. As such, you can’t shrink it, and definitely can’t add to it—shrinking it would just leave a block of garbage memory that would probably be too small to be used, and adding to it would mean taking up more memory—it could very well encroach into a block of memory that was being used elsewhere, and that would lead to very weird results. This inflexibility has an advantage though—there is only one static block of memory, and so it is very efficient. NSMutableString has a different implementation—the details of which are not public—which most likely involves multiple linked “blocks” of RAM. This linkage allows flexibility, but comes at a price of efficiency. It takes time to look up the next block and go to it (again, it’s all relatively speaking, but in the time that it take to look up the next block of memory, the system could conceptually have loaded two or even four characters, depending on if memory addresses were 32-bit or 64-bit. Each character is 16-bit). As a comparison, Java allows you to concatenate strings by using the + operator. How does it do this? By copying the old string into a new block of memory, then putting the new bit to the end of the new, bigger block. Not very efficient.

So,

When Should You Use Mutable?

A mutable string should be used when you are physically changing the value of the existing string, without completely discarding the old value. Examples might include adding a character to the beginning or the end, or changing a character in the middle. With a mutable string, you can do this “in place”—you’ll just modify the existing string. By contrast, an immutable string, once its value is set, cannot change that value. NSString has methods such as stringByAppendingString:, which does add a string to an existing one—but it returns a new string. Behind the scenes, NSString has copied your old string to a new (larger) memory location, added the argument, and returned the new string. That copying is a lot less efficient (relatively speaking, or if you have to do it a lot).

Of course, there’s nothing stopping you from physically assigning one string to another. Old values will be overwritten. Most NSStrings, including the @”String Constants”, are autoreleased. If you are creating a new string and you decide to alloc/init, you can then assign it to another value without consequence:

myString = anotherString;
myString = myTextField.text;

You can do this with both mutable and immutable strings. The main takeaway is that you should only use mutable when your changing the string itself. But you can change the variable with both mutable and immutable strings without compiler or runtime issues (short of memory management, but most of it is autoreleased anyway).

Extension 14: Advanced KVC


Last week’s Lesson covered the basics of KVC, and it is those features that would be used 90% of the time. But KVC has some more to offer. Let’s take a look.

Batch Processing

Another one of KVC’s methods is dictionaryWithValuesForKeys:. The single argument is an array of strings. From that, the invokes valueForKey: with each key, and returns a dictionary with the keys and values. For example, to get some attributes of a piece of merchandise from our hypothetical store, we could use the following code:

Merchandise *product = [[store valueForKeyPath:@"merchandise"] lastObject];	// Last object in array
NSArray *keys = [NSArray arrayWithObjects: @"brand", @"price", @"department", @"shelf", @"netWeight", nil];
NSDictionary *productInfo = [product dictionaryWithValuesForKeys:keys];

You could then use this dictionary in an inventory tracking program, for example.

This method also has a counterpart, setValuesForKeysWithDictionary:. Called on an instance of any object, this method goes through each key in the dictionary, and replaces that key’s value in the object with the new value.

nil Values

Here is one minor issue that you might run into with KVC. You can’t put nil into a dictionary (or array for that matter), because nil tells the collection that it’s the end of data. Therefore, you have to use [NSNull null] instead, and that’s the value you’ll get back if you call valueForKey: on an object type. But what happens if you try to set nil for a scalar type, such as an integer? By default, you get an error at runtime. Therefore, you have to override setNilValueForKey: and define your own implementation. In our store, the method might look like this:

- (void)setNilValueForKey:(NSString *)key {
	if ([key isEqualToString:@"price"])
		[self setValue:[NSNumber numberWithInt:0] forKey:@"price"];
	else
		[super setNilValueForKey:key];
}

Error Handling

What happens if you try to access or set a value for a key that doesn’t exist? In general, you get the compiler or runtime warning that looks like “this class is not key value coding-compliant for the key someKeyThatDoesn’tExist.” Fortunately, when KVC encounters this it will ask the class what to do. As such, there are two methods that you can override: valueForUndefinedKey: and setValue:forUndefinedKey:.

A simple way to handle this issue is to simply tell the user that the key is invalid. So to protect our store from crashes, we’re going to just do that:

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
	NSLog(@"Cannot set anything for this key. The key %@ is not valid.", key);
}

- (void)valueForUndefinedKey:(NSString *)key {
	NSLog(@"Cannot get value for this key. The key %@ is not valid.", key);
}

Obviously, KVC is a very powerful feature, and allows you to build very robust, abstract applications. In fact, it is the core data access mechanism in Core Data, Apple’s framework for accessing data from a database. But that’s a complex topic for another day.

Objective-C Lesson 13: Key-Value Coding


Accessing ivars is usually done through accessor methods or dot-notation. But as a means of indirection, there is another way—Key-Value Coding, or KVC. This is a means of setting and getting the values by using strings—specifically, NSString, and its corresponding methods, including the very useful stringWithFormat:.

Methods

KVC involves another layer of abstraction, in the form of two specific methods: -valueForKey: and -setValue:forKey:. These methods work as they do for NSDictionary (which, unsurprisingly, is built upon the same principles). The key is an NSString, constructed as a constant or with any one of NSString’s methods. The code is simple:

NSString *name = [myObject valueForKey:@“name”];

The key is in fact the same name as your variable. It follows a specific sequence of steps:

  1. First, it looks for a getter method with the same name. In the above example, it looks for the -name or -isName (for boolean values) methods; if they are found, it invokes that method and returns that result.
  2. If the getter methods are not found, the method looks for an instance variable by that name: name or _name.

This is a very important mechanism: -valueForKey: uses the metadata in the runtime stack to look into your custom objects. This ability is not available in other languages. Speaking of other languages, experienced Java programmers are familiar with the concepts of autoboxing—converting int and other scalar types into corresponding object types, such as Integer and Double. KVC is the only Objective-C construct that supports autoboxing—it automatically converts scalar types to NSNumbers or NSValues. It will also do the opposite if you set one of these types to a scalar value. Note, however, you must still manually “box” a scalar value before using it in the setValue:ForKey: method:

[self setValue:[NSNumber numberWithFloat:249.42] forKey:@“price”];

If price is a float, the value will be automatically unboxed.

Key Paths

You can combine KVC and dot syntax to create a key path. Imagine that we have a store class; we can use the following syntax:

[store setValue:[NSNumber numberWithFloat:2.99] forKeyPath:@“gallonOfMilk.price];

That is the same as

store.gallonOfMilk.price = 2.99;

These key paths can be as deep as you want them to be.

Aggregated Results

NSArray *prices = [store valueForKeyPath:@“merchandise.price”];
// Merchandise is an array

If you ask an NSArray for a value for a key, it will create another array, ask each object for the value specified in the key path, and adds these values to the new array. It basically loops over each value in the array, and sends each object the method valueForKeyPath:@“price”.

Advanced Operators

  • @count:
    count = [store valueForKeyPath:@“merchandise.@count”];

    The @count directive tells the KVC mechanism to get the count of the result of the rest of the key path.

  • @sum:
    totalPrice = [store valueForKeyPath:@“merchandise.@sum.price”];

    The @sum directive gets the sum of all the requested values—in this case, the sum of all the prices of the merchandise.

  • @avg:
    avgPrice = [store valueForKeyPath:@“merchandise.@avg.price];

    The @avg directive gets the average of all the values.

  • @min and @max:
    minPrice = [store valueForKeyPath:@“merchandise.@min.price”];
    maxPrice = [store valueForKeyPath:@“merchandise.@max.price];

    These two are self-explanatory: they return the maximum or minimum of all the values in the range.

  • @distinctUnionOfObjects:
    NSArray *brands = [store valueForKeyPath:@“merchandise.@distinctUnionOfObjects.brand”];

    This key returns a list of individual distinct values—here, it returns a list of all the brands in our hypothetical store.

Note that, unfortunately, you cannot add your own operators.

One More Application

Imagine that you were creating a lottery application (or more likely, a lottery view within another application). You might have 10 views, each with a number, and you highlight each image as a number is drawn. In this case, you’d probably have ten instance variables, maybe named numberView1, numberView2, all the way to numberView10. To light up the views, you could have a large if…else or switch block, comparing the new value to all the values 1–10:

int nextNum = arc4random() % 10 } 1;	// Random number generator, 1–10
    switch (nextNum) {
        case 1:
            // Highlight
            break;
        // etc.
    }

Knowing KVC though, there is a more elegant solution:

[[self valueForKey:[NSString stringWithFormat:@“numberView%d”, nextNum]] highlight];	// Assume highlight method exists and works

Update: That method can be found in this sample project: Click here to download.

Objective-C Lesson 9: Protocols


A protocol is a list of method declarations that is not bound to any one class. The methods are not implemented in the protocol; instead, classes conform to or adopt a protocol and within those classes the methods are implemented. A protocol is simply a grouping of certain related methods under one name, and it acts like a contract—conforming classes must implement the required methods (and may implement any of the potential optional methods).

The syntax for declaring a protocol is simple:

@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end

The text in bold is required syntax. The name of the protocol is written in italics. Between the mandatory lines is the method(s) of the protocol, declared as you would normally declare methods. The protocol is typically saved in a .h (header) file, and follow the same naming conventions as classes do.

For a class to adopt one or more protocols, place the protocol names between angle brackets, separated by commas if there is more than one. A class that adopts the

NSCopying

protocol might be declared like this:

@interface CopyMachine : NSObject <NSCopying, NSCoding>

The compiler sees that the CopyMachine class conforms to the NSCopying and NSCoding protocols, and it will issue a warning if the required methods in those classes are not implemented. Note also that protocol conformity is inherited—subclasses of CopyMachine, for example, will also conform to those protocols, and can re-implement (override) those methods as necessary.

Let’s look at the theory behind protocols.

Why Protocols?

Apple’s documentation on protocols states that there are at least three reasons to use protocols:

  • To declare methods for others to implement
  • To declare the public interface to a class while hiding the nature of the class itself
  • To mark similarities between classes that are not part of the same inheritance tree

In fact, there is a fourth reason as well, and in everyday use it is the most compelling: It lets you avoid the complexities of subclassing, similar to the way categories do, but in a different manner.

Protocols play an important role in OS X and iOS development—a lot of built-in classes use them. A classic example is the UITableViewController, which is a view controller that manages a table view (basically a scrollable list, like in the iPod application). Without protocols, users of the class would have to subclass the original class, deal with any issues, and override the original methods. This is another challenge—for the original class. For something like a table view, where the data for the view may come from a variety of locations and there may be a myriad of behaviors to handle, what is an acceptable default implementation? Using protocols circumvents the issue. UIKit also includes two protocols, designed to work with UITableViewControllers. They are UITableViewDataSource and UITableViewDelegate. Any class that adopts these protocols will be able to control a table view.

Apple’s documentation on protocols effectively describes the other reasons. Let’s return to the syntax.

Other Protocol Functionality

Optional Methods

Methods in a protocol can be declared to be optional, by using the @optional directive. This works like the ones for instance variable scope—it acts like a switch. The opposite is @required.

@protocol Drawing
- (void)paint
- (void)erase
@optional
-(void)outline
@end

Introspection

You can check to see if a class implements a protocol by calling the conformsToProtocol: method. The single argument is of type Protocol, declared with the @protocol (protocolName) directive.

if ([someObject conformsToProtocol:@protocol(NSCopying)])   …

Applications with id type

The id type is designed to be for any object type, but you can use the compiler to ensure that only objects that conform to a protocol are assigned to the object. Note that this only works with a statically type object being assigned to the id type, as it is a compiler check. This type of usage is often found when classes have an ivar or property for their delegate, which is an id type that conforms to a corresponding delegate protocol. The syntax looks like this:

id <NSCopying> delegate;

Remember that this is a compiler check, so it only works with statically typed variables and objects.

Java Interfaces

Java programmers may recognize the similarity between protocols and Java’s interfaces. In fact, the former was the inspiration for the latter. The main benefit of interfaces in Java is so that a collection can hold a number of objects of different classes, which could all be upcast to a shared interface—an object could implement many interfaces. Because NSArray can already hold objects of different types without limitations, this is not the intention of protocols in Objective-C. Rather, protocols are used extensively in Cocoa as a communications medium. This best explained by Apple’s documentation on delegation:

“A delegate is an object that acts on behalf of, or in coordination with, another object when that object encounters an event in a program. The delegating object is often a responder object—that is, an object inheriting from NSResponder in AppKit or UIResponder in UIKit—that is responding to a user event. The delegate is an object that is delegated control of the user interface for that event, or is at least asked to interpret the event in an application-specific manner.

To better appreciate the value of delegation, it helps to consider an off-the-shelf Cocoa object such as a text field (an instance of NSTextField or UITextField) or a table view (an instance of NSTableView or UITableView ). These objects are designed to fulfill a specific role in a generic fashion; a window object in the AppKit framework, for example, responds to mouse manipulations of its controls and handles such things as closing, resizing, and moving the physical window. This restricted and generic behavior necessarily limits what the object can know about how an event affects (or will affect) something elsewhere in the application, especially when the affected behavior is specific to your application. Delegation provides a way for your custom object to communicate application-specific behavior to the off-the-shelf object.

The programming mechanism of delegation gives objects a chance to coordinate their appearance and state with changes occurring elsewhere in a program, changes usually brought about by user actions. More importantly, delegation makes it possible for one object to alter the behavior of another object without the need to inherit from it. The delegate is almost always one of your custom objects, and by definition it incorporates application-specific logic that the generic and delegating object cannot possibly know itself.”

  • Welcome

    My goal is to make CupsOfCocoa into a beautiful source for beginners to the iPhone platform to get started. Subscribe below for more, and stay tuned!

  • Contact Me

    If you need to contact me for any reason, feel free to send me an email.
  • The Giving Spirit

    If you've found this site helpful, would you consider donating a little sum? Any amount is appreciated...Thanks so much!

  • Roadmap

  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 220 other followers

  • Back to the Past

    May 2020
    S M T W T F S
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  
  • Time Machine

  • You count!

    • 622,650 views
  • Worldwide Stats

    free counters
%d bloggers like this: