Protocols and Delegation
A protocol, declared with @protocol ProtocolName ... @end, defines a list of method signatures that any class can promise to implement without dictating what that class inherits from, which is Objective-C's answer to interfaces in languages like Java. A class declares conformance by listing the protocol name in angle brackets after its superclass, @interface FileDownloader : NSObject <URLSessionDownloadDelegate>, and the compiler then checks that the class actually implements every required method the protocol declares.
Cricket analogy: Like an ICC-certified umpire qualification that any official can earn regardless of which cricket board they belong to, a protocol defines a set of responsibilities any class can adopt regardless of what it inherits from.
Required and Optional Protocol Methods
By default, every method listed in a protocol is @required, meaning any conforming class must implement it or the compiler emits a warning, but methods after an explicit @optional marker are not mandatory, and calling an optional method safely requires checking [delegate respondsToSelector:@selector(methodName)] first to avoid sending a message the object doesn't implement. This required/optional split is exactly how UIKit's table view and text field delegates work: cellForRowAtIndexPath: is required for a UITableViewDataSource to function at all, while textFieldShouldReturn: is optional and only called if the delegate chose to implement it.
Cricket analogy: Like an ICC playing-conditions rulebook marking the toss and the scorecard as mandatory for every match while marking DRS reviews as optional depending on the series agreement, protocols mark some methods @required and others @optional.
Delegation: Protocols in Practice
Delegation is the design pattern where one object (the delegate) is handed responsibility for certain decisions or notifications on behalf of another object, and it's implemented by declaring a weak property typed as id<SomeProtocol> on the object doing the delegating, so that object can call methods on whatever delegate object was assigned to it without knowing or caring about that delegate's concrete class. The delegate property is declared weak rather than strong specifically to avoid a retain cycle, since the delegating object typically also being retained by the delegate (directly or indirectly) would otherwise create two objects each keeping the other alive forever.
Cricket analogy: Like a captain delegating the decision of when to review a decision via DRS to a specific senior player on the field, without needing to know their batting technique, only that they can make that specific call, delegation hands one specific responsibility to any object conforming to the right protocol.
// DownloadTaskDelegate.h
@protocol DownloadTaskDelegate <NSObject>
@required
- (void)downloadTask:(id)task didFinishWithData:(NSData *)data;
@optional
- (void)downloadTask:(id)task didUpdateProgress:(float)progress;
@end
// DownloadTask.h
@interface DownloadTask : NSObject
@property (nonatomic, weak) id<DownloadTaskDelegate> delegate;
- (void)start;
@end
// DownloadTask.m
@implementation DownloadTask
- (void)start {
NSData *result = [self fetchData];
if ([self.delegate respondsToSelector:@selector(downloadTask:didUpdateProgress:)]) {
[self.delegate downloadTask:self didUpdateProgress:1.0];
}
[self.delegate downloadTask:self didFinishWithData:result]; // required, always safe to call
}
@end
// ViewController.m adopts the protocol
@interface ViewController () <DownloadTaskDelegate>
@end
@implementation ViewController
- (void)startDownload {
DownloadTask *task = [[DownloadTask alloc] init];
task.delegate = self;
[task start];
}
- (void)downloadTask:(id)task didFinishWithData:(NSData *)data {
NSLog(@"Download finished with %lu bytes", (unsigned long)data.length);
}
@endA protocol can itself inherit from other protocols, for example @protocol MyDataSource <NSObject> ensures any class conforming to MyDataSource is also guaranteed to respond to NSObject's own methods like description and respondsToSelector:, which is why nearly every custom protocol you write should inherit from NSObject.
Declaring a delegate property as strong instead of weak is a classic retain-cycle bug: if the delegating object (like DownloadTask) is strongly retained by its delegate (like a ViewController holding onto its task), and the task also strongly retains the delegate back, neither object's memory is ever released.
- A protocol declares method signatures with @protocol...@end without dictating a class's inheritance.
- A class adopts a protocol by listing it in angle brackets after its superclass, e.g. <DownloadTaskDelegate>.
- Methods are @required by default; methods after @optional are not mandatory to implement.
- respondsToSelector: should be checked before calling an optional protocol method.
- Delegation hands specific decisions to another object typed as id<ProtocolName>, decoupling concrete classes.
- Delegate properties are declared weak to avoid retain cycles between the delegating object and its delegate.
- Protocols can inherit from other protocols, most commonly from NSObject.
Practice what you learned
1. What does @protocol define, and how does it differ from a class?
2. By default, are methods listed in a protocol required or optional?
3. Why should you call respondsToSelector: before invoking an optional protocol method on a delegate?
4. Why is a delegate property typically declared weak rather than strong?
5. What type is commonly used to declare a delegate property that can hold any object conforming to a given protocol?
Was this page helpful?
You May Also Like
Inheritance in Objective-C
How Objective-C's single-inheritance class hierarchy works, including method overriding, calling super, and designated initializers.
Classes and Objects in Objective-C
How Objective-C classes are declared with @interface/@implementation, and how objects are created via alloc and init.
Categories and Extensions
How Objective-C categories add methods to existing classes without subclassing, and how class extensions expose private, writable state.
Strong, Weak, and Retain Cycles
A deep look at how strong and weak references interact under ARC, and practical patterns for detecting and breaking retain cycles.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics