A protocol is the declaration (as opposed to implementation) of a set of methods and/or properties in a header file (usually with the extension of .h). Any object that you declare to conform to such protocol is responsible for writing the implementation of those methods and properties, depending on whether the protocol specifies them as required or optional.
Think of protocols as sets of rules, with some rules being
optional and others mandatory. Any object saying that it conforms to
that protocol must follow those rules. Let’s see a simple example of this. We will go ahead and
define a protocol called Person
Protocol
. For
this, you need to create a new protocol file, so follow these steps
first:
In Xcode, while your project is open, go to the File menu and then choose New → New File...
Now make sure iOS is the main category on the left side of the New File dialog and then choose the Cocoa Touch subcategory. Once that is done, choose the Objective-C Protocol item and press Next (see Figure 1-26).
Now you will be asked to save this file and specify a name for it. Give it the name
PersonProtocol
and press Save (see Figure 1-27).
Now we have our header file. Let’s get on with the actual
declaration of our protocol. Our objective with this new Person
Protocol
protocol is to govern the rules on
any class that impersonates a “Person,” or in other
words, says that it is a Person class. For instance, in your
application, you can have a class named Infant, Mother, Father, Son,
Daughter, Stranger, etc. You can then make
all these classes conform to the Person
Protocol
protocol, which will define the types of behavior each of these
classes must implement. Let’s say that, for every person, we
need at least a first name, a last name, and an age:
#import <Foundation/Foundation.h>
@protocol
PersonProtocol
<
NSObject
>
@property
(
nonatomic
,
strong
)
NSString
*
firstName
;
@property
(
nonatomic
,
strong
)
NSString
*
lastName
;
@property
(
nonatomic
,
unsafe_unretained
)
NSUInteger
age
;
@end
Now let’s create a class called Father and make sure that this
class conforms to our PersonProtocol
protocol. To create this class, follow these steps:
In Xcode, while in your project, go to the File menu and then select New → New File...
In the New File dialog, make sure iOS is the main category and then choose the Cocoa Touch subcategory. After that is done, select the Objective-C class item in the list on the righthand side. Now press the Next button (see Figure 1-28).
In this screen (see Figure 1-29), make sure we are creating a subclass of
NSObject
. Once that is done, press the Next button.Now you are asked to save the new class. Give it the name of Father, and press the Create button (see Figure 1-30).
Fantastic, we now have our Father
class and the PersonProtocol
protocol. Open the header file
of the Father
class and make sure
that it conforms to the PersonProtocol
protocol:
#import <Foundation/Foundation.h>
#import "PersonProtocol.h"
@interface
Father
:NSObject
<
PersonProtocol
>
@end
Now if you attempt to compile your app (by pressing Command+Shift+R simultaneously), you will get warnings from the compiler, similar to those shown in Figure 1-31.
As you can see, the compiler understands that the Father
class wants to conform to the PersonProtocol
protocol. However, the Father
class isn’t implementing the required
setter and getter methods of the properties defined in the PersonProtocol
protocol. We are seeing these
warnings because anything defined in a protocol by default is required
from its conforming classes. Required methods and properties in a
protocol can explicitly be marked with the @required
keyword. If you want to specify that
followers of a protocol are free to choose to implement or not implement
your methods or properties, you can simply tell the compiler that those
methods/properties are optional, using the @optional
keyword.
Let’s go back to PersonProtocol.h and mark the firstName
, lastName
, and age
properties as optional, but add a method
to the protocol called breathe
and
make it a required method, because, let’s face it, everybody has got to
breathe:
#import <Foundation/Foundation.h>
@protocol
PersonProtocol
<
NSObject
>
@
optional
@property
(
nonatomic
,
strong
)
NSString
*
firstName
;
@property
(
nonatomic
,
strong
)
NSString
*
lastName
;
@property
(
nonatomic
,
unsafe_unretained
)
NSUInteger
age
;
@
required
-
(
void
)
breathe
;
@end
Now if you compile your application, you will get completely different warnings (see Figure 1-32).
Now if you go to the Father
class and define and implement the breathe
method, even if the method
implementation is empty, the compiler will be happy with that. Remember,
the Father
class now doesn’t have to
implement the three aforementioned properties because they are now
defined as optional in the PersonProtocol
protocol. Here is now the
correct definition of the Father
class:
#import <Foundation/Foundation.h>
#import "PersonProtocol.h"
@interface
Father
:NSObject
<
PersonProtocol
>
-
(
void
)
breathe
;
@end
And here is the correct implementation of the Father
class:
#import "Father.h"
@implementation
Father
-
(
void
)
breathe
{
/* Implement this method here */
}
@end
Attempt to compile your app now and you’ll notice that the compiler is perfectly happy with our implementation.
Cocoa Touch has given protocols a really nice meaning in Objective-C. In Cocoa Touch, protocols are the perfect means for defining delegate objects. A delegate object is an object that another object consults when something happens in that object. For instance, a repairman is the delegate for a broken-down car. If something happens to your car, you go to your repairman and ask him to fix the car for you (although some prefer to repair the car themselves, in which case they are their own delegate for their car). So in Cocoa Touch, many classes expect a delegate object and make sure that whatever object is assigned as their delegate conforms to a certain protocol.
For instance, as we will see in Chapter 4, the UITableView
class defines and implements a
property called delegate
, which is
required to conform to the UITableViewDelegate
protocol. This protocol
simply lays down the law to those objects that want to become the
delegate object of a table view. The protocol requires those objects to
implement certain methods or in some cases, specifies that some
methods/properties are optional so the delegate object is free to
implement or not implement them. Now, when a user selects a row in a
table, the UITableView
can call the
tableView:didSelectRowAtIndexPath:
method with the assurance that the UITableViewDelegate
at least defined the
method. The method may be correctly or incorrectly coded, but at least
it’s present, so the program won’t crash at runtime because of a
nonexistent method (selector).
Get iOS 6 Programming Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.