CG@CPPBLOG

/*=========================================*/
随笔 - 76, 文章 - 39, 评论 - 137, 引用 - 0
数据加载中……

用OBJC编程 5 - Working with Protocols

用OBJC编程 5 - Working with Protocols

协议定义了交互的消息
@protocol XYZPieChartViewDataSource
- (NSUInteger) numberOfSegments;
- (CGFloat)    sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
- (NSString *) titleForSegmentAtIndex:(NSUInteger)segmentIndex;
@end

数据源作为View的一个属性,只要是符合协议的对象就可以,所以类型是id。
@interface XYZPieChartView : UIView
@property (weak) id <XYZPieChartViewDataSource> dataSource;
@end
委托和数据源属性通常声明为weak,以避免强引用循环。

设置属性为一个不符合协议的对象,将会引起一个编译时警告。

可选方法,使用@optional 和 @required
@protocol XYZPieChartViewDataSource
- (NSUInteger) numberOfSegments;
- (CGFloat)    sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
@optional
- (NSString *) titleForSegmentAtIndex:(NSUInteger)segmentIndex;
- (BOOL)       shouldExplodeSegmentAtIndex:(NSUInteger)segementIndex;
@required
- (UIColor *)  colorForSegmentAtIndex:(NSUInteger)segementIndex;
@end

运行时检查可选方法
如果一个方法是可选的,那么在调用前应该检查它是否实现。
NSString *thisSegmentTitle; // Local object variables are automatically initialized to nil
if([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]){
    thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
}

respondsToSelector: 方法用了一个selector,@selector。
如上定义一个符合协议的id类型,调用respondsToSelector,会产生一个编译时错误,解决方案是声明对象符合NSObject协议

从协议继承
最佳实践是,你的协议依从NSObject协议。NSObject对象依从NSObject协议。
一旦你的协议依从NSObject协议,那么依从你协议的任何对象都必须实现NSObject协议的方法,但因为它们应该是NSObject的子类,你就不必自己实现这些NSObject的方法。依从NSObject协议非常有用。
@protocol MyProtocol <NSObject>

@end

comform 一个协议
@interface MyClass : NSObject <MyProtocol, AnotherProtocol>

@end
如果一个类声明了大量的协议,意味着代码需要重构成多个小的类。

一旦声明依从某个协议,就必须实现所有的required方法,和需要的optional方法,否则编译器会给出警告。方法的签名必须相同。

Cocoa 和 Cocoa Touch 定义了大量的protocol
  • view的数据源协议
  • view的委托协议delegate
  • 一些类似的类,但是无继承关系,比如NSArray和NSDictionary依从NSCoding协议
  • 一些OBJC语言级特性,也依赖协议,如一个容器需要依从NSFastEnumeration协议才能使用快速枚举fast enumeration;copy的属性依从NSCopying协议,否则会得到一个运行时异常。

为匿名使用协议

有时候,一个框架的开发者为了向使用者隐藏一个类,只把它的接口通过协议暴露

id <XYZFrameworkUtility> utility = [frameworkObject anonymousUtility];

例如NSFetcheResultsController
NSInteger sectionNumber = //,,,
id <NSFetchedResultSectionInfo> sectionInfo = 
          [self.fetchedResultsController.sections objectAtIndex:sectionNumber];
NSInteger numberOfRowsInSection = [sectionInfo numberOfObjects];





posted on 2013-11-21 09:32 cuigang 阅读(206) 评论(0)  编辑 收藏 引用 所属分类: OBJC


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理