【发布时间】:2008-11-26 23:15:30
【问题描述】:
我注意到在 iPhone SDK 中定义的几个协议中标记为可选的方法,例如 UIActionSheetDelegate 协议。
如何定义自己的协议,并将其中一些方法设置为可选?
【问题讨论】:
标签: iphone objective-c
我注意到在 iPhone SDK 中定义的几个协议中标记为可选的方法,例如 UIActionSheetDelegate 协议。
如何定义自己的协议,并将其中一些方法设置为可选?
【问题讨论】:
标签: iphone objective-c
来自“Formal Protocols”上的 Apple 页面:
可选协议 方法可以标记为可选 使用@optional 关键字。 对应@optional modal 关键字,有一个@required关键字 正式表示的语义 默认行为。您可以使用 @optional 和 @required 进行分区 如您所见,您的协议分为多个部分 合身。如果您不指定任何 关键字,默认为@required。
@protocol MyProtocol
- (void)requiredMethod;
@optional
- (void)anOptionalMethod;
- (void)anotherOptionalMethod;
@required
- (void)anotherRequiredMethod;
@end
【讨论】:
如果协议中的方法被标记为可选,则必须在尝试调用之前检查对象是否实现了该方法。
例如,饼图视图可能会像这样测试段标题方法:
NSString *thisSegmentTitle;
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
}
respondsToSelector: 方法使用一个选择器,它指的是编译后的方法的标识符。您可以通过使用 @selector() 指令并指定方法的名称来提供正确的标识符。
如果本例中的数据源实现了该方法,则使用标题;否则,标题保持为零。
【讨论】:
@protocol MyProtocol <NSObject>
协议是一组规则。我们可以创建如下的协议:
TestProtocols.h
@protocol TestProtocols <NSObject>
@optional
-(void)testMethodOptional;
@required // by default
-(void)testMethodRequired;
@end
实施:
TestClass.h
#import "TestProtocols.h"
@interface TestClass : NSObject <TestProtocols>
@end
TestClass.m
#import "TestClass.h"
@implemenation TestClass
//optional to implement
-(void)testMethodOptional{
// Your Code
}
//required to implement
-(void)testMethodRequired{
// Your Code
}
@end
【讨论】:
在方法声明之前使用@optional 关键字使其成为可选。就这么简单!
// myProtocol.h
@protocol myProtocol
- (void)myMandatoryMethod:(id)someArgument;
@optional
- (void)myOptionalMethod:(id)someArgument;
@end
// myClass.m
@interface myClass : someSuperClass <myProtocol>
//...
@end
【讨论】:
协议与抽象类的作用相同,因此@optional 关键字定义了那些对于实现来说是可选的方法。
所以,在代码中,someMethod1、someMethod2 和 someMethod4 是必需的方法(必须实现)。 someMethod3 是可选的——如果我们没有实现这个方法,编译器不会抛出任何警告。
@protocol myPrtocol<NSObject>
-(void)someMethod1:(id)someArgument;
-(void)someMethod2:(id)someArugument;
@optional
-(void)someMethod3:(id)someArgument;
@required //by default
-(void)someMethod4:(id)someArgument;
@end
// sampleClass.m
@interface sampleClass : someSuperClass <myProtocol>
//...
@end
【讨论】: