今天讲Objective-C的protocol的两个知识点,分别是带可选方法的协议,以及在运行时时检查可选方法是否实现。
Protocols Can Have Optional Methods
By default, all methods declared in a protocol are required methods. This means that any class that conforms to the protocol must implement those methods.
It’s also possible to specify optional methods in a protocol. These are methods that a class can implement only if it needs to.
As an example, you might decide that the titles on the pie chart should be optional. If the data source object doesn’t implement the titleForSegmentAtIndex:, no titles should be shown in the view.
You can mark protocol methods as optional using the @optional directive, like this:
@protocol XYZPieChartViewDataSource
- (NSUInteger)numberOfSegments;
- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
@optional
- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
@end
In this case, only the titleForSegmentAtIndex: method is marked optional. The previous methods have no directive, so are assumed to be required.
The @optional directive applies to any methods that follow it, either until the end of the protocol definition, or until another directive is encountered, such as @required. You might add further methods to the protocol like this:
@protocol XYZPieChartViewDataSource
- (NSUInteger)numberOfSegments;
- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
@optional
- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
- (BOOL)shouldExplodeSegmentAtIndex:(NSUInteger)segmentIndex;
@required
- (UIColor *)colorForSegmentAtIndex:(NSUInteger)segmentIndex;
@end
Check that Optional Methods Are Implemented at Runtime
If a method in a protocol is marked as optional, you must check whether an object implements that method before attempting to call it.
As an example, the pie chart view might test for the segment title method like this:
NSString *thisSegmentTitle;
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
}
The respondsToSelector: method uses a selector, which refers to the identifier for a method after compilation. You can provide the correct identifier by using the @selector() directive and specifying the name of the method.
If the data source in this example implements the method, the title is used; otherwise, the title remains nil.
Remember: Local object variables are automatically initialized to nil.
If you attempt to call the respondsToSelector: method on an id conforming to the protocol as it’s defined above, you’ll get a compiler error that there’s no known instance method for it. Once you qualify an id with a protocol, all static type-checking comes back; you’ll get an error if you try to call any method that isn’t defined in the specified protocol. One way to avoid the compiler error is to set the custom protocol to adopt the NSObject protocol.