《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个方法》要点回顾(四)第四章 协议与分类

OC中两项重要的语言特性:

  • 协议:与Java中的“接口”类似,但不支持多重继承,最常见的用途是实现委托模式

    多重继承指的是一个类可以同时继承多个类,比如A类继承自B类和C类,这就是多重继承。

  • 分类:利用分类机制,我们无须继承子类即可直接为当前类添加方法。因为OC运行期系统是高度动态的,但也隐藏着一些陷阱。

23. 通过委托与数据源协议进行对象间通信

@property (nonatomic, weak) id  delegate;

如果是方法是可选的(optional),在委托类中,需要先执行判断(responseToSelector)操作。

if ([_delegate responseToSelector:@selector(xxxxx)]) {
    [_delegate xxxxx];
}
完整的例子:
//
//  EOCNetworkFetcher.h
//

#import 

@class EOCNetworkFetcher;
@protocol EOCNetworkFetcherDelegate 

@optional
- (void)networkFetcher:(EOCNetworkFetcher *)fetcher didReceiveData:(NSData *)data;

- (void)networkFetcher:(EOCNetworkFetcher *)fetcher didFailWithError:(NSError *)error;

- (void)networkFetcher:(EOCNetworkFetcher *)fetcher didUpdateProgressTo:(float)progress;

@end

@interface EOCNetworkFetcher : NSObject

@property (nonatomic, weak) id  delegate;

- (void)requestWithParams:(id)params url:(NSURL *)url;


@end
/*******************************************/
/*******************************************/
//
//  EOCNetworkFetcher.m
//

#import "EOCNetworkFetcher.h"

@interface EOCNetworkFetcher (){
    /**
    这个结构体,用来缓存委托对象是否能响应特定的选择子
    2^1 = 2,表示0 和 1 两个数。
    */
    struct {
        unsigned int didReceiveData: 1;
        unsigned int didFailWithError: 1;
        unsigned int didUpdateProgressTo: 1;
    } _delegateFlags;
}
@end

@implementation EOCNetworkFetcher {}

- (void)setDelegate:(id)delegate {
    
    _delegate = delegate;
    
    /* 优化代码执行速度
     这样就不用每次在实现要被代理的方法前,每次执行检查了。只要检查一次就好。因为在设置代理时就已经确定了。
     */
    _delegateFlags.didReceiveData = [delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)];
    _delegateFlags.didFailWithError = [delegate respondsToSelector:@selector(networkFetcher:didFailWithError:)];
    _delegateFlags.didUpdateProgressTo = [delegate respondsToSelector:@selector(networkFetcher:didUpdateProgressTo:)];
    
}

- (void)requestWithParams:(id)params url:(NSURL *)url {
    
    if (_delegateFlags.didReceiveData) {
        [_delegate networkFetcher:self didReceiveData:[NSData new]];
    }
    
    if (_delegateFlags.didFailWithError) {
        [_delegate networkFetcher:self didFailWithError:[NSError new]];
    }
    
    if (_delegateFlags.didUpdateProgressTo) {
        [_delegate networkFetcher:self didUpdateProgressTo:1.0f];
    }
}

@end

要点

  • 委托模式为对象提供了一套接口,使其可由此将相关事件告知其他对象。
  • 将委托的对象应该支持的接口定义成协议,在协议中将可能需要的事件定义成方法。
  • 当某一对象需要从另一对象获取数据时,可以使用委托模式。在这种情况下,该协议被称为 “数据源协议”。
  • 若有必要,可实现含有位段的结构体,将委托对象是否响应相关代理方法 这一信息缓存至其中。

在结构体中,
fileA 位段将占用8个二进制位,0~255;
fileB 位段将占用4个二进制位,0~16;
fileC 位段将占用2个二进制位,0~4;
fileD 位段将占用1个二进制位,0~1;

struct file {
    unsigned int fileA: 8;
    unsigned int fileB: 4;
    unsigned int fileC: 2;
    unsigned int fileD: 1;
} ;

24. 将类的实现代码分散到便于管理的数个分类之中

要点
  • 使用 分类机制 把类的实现代码划分为易于管理的小块。
  • 将应该视为 “私有” 的方法归入名为 “private” 的分类中,用以隐藏实现细节。

将类代码打散到分类中,便于调试

  1. 调试会出现分类名称,如-[EOCPerson(FriendShip) addFriend:]
  2. 方便查看,可以给类进行“瘦身”。

25. 总是为第三方类的分类名称加上前缀

@interface NSString (WZZ_HTTP)

- (NSString *)wzz_doSomeThing1;

- (NSString *)wzz_doSomeThing2;

@end
要点总结
  • 向第三方类中添加分类时,总应给其 名称 和其中的 方法 加上你专用的前缀。----避免多次覆盖

26. 勿在分类中声明属性

属性,是用来封装数据的。

要点
  • 把封装数据所用的全部属性都定义在 主接口 里;
  • 在 “class-continuation 分类” 之外的所有分类里,可以定义存取 方法 ,但不应声明 属性 。

27. 使用 “class-continuation” 分类实现隐藏细节

@interface EOCPerson ()

@end

//或
@implementation EOCPerson

@end
要点
  • 通过 “class—continuation分类” ,向类中增加实例变量。
  • 如果属性在主接口声明中为“只读” ,而类的内容又要用设置方法修改此属性,那么就在 “class-continuation分类” 中将其扩展为可读写。
//.h 中
@property (nonatomic, copy, readOnly) NSString *name;

//.m 中
@property (nonatomic, copy, readWrite) NSString *name;
  • 把私有方法的原型声明在 “class-continuation分类” 里面。
//.m
@interface EOCPerson ()
- (void)p_privateMethod;//私有方法
@end
  • 若想隐藏此类所实现的协议,则可在该类的 “class-continuation分类” 中声明。
//.m
@interface EOCPerson() 
@end

28. 通过协议提供匿名对象

要点
- (id)doSomeThing;
  • 协议在某种程度上可以提供匿名类型。具体的类型可以淡化成遵从某协议的id类型,协议里规定了对象所应实现的代理方法。
  • 使用匿名对象来隐藏类型名称(或类名)
  • 如果类型不重要,重要的是对象能够响应(某个协议的)特定方法,那么可以使用你匿名对象来表示。

系列文章

  • 第一章 熟悉 Objective-C
  • 第二章 对象、消息、运行期
  • 第三章 接口和API设计
  • 第五章 内存管理
  • 第六章 块(block)与大中枢派发(GCD)
  • 第七章 系统框架

你可能感兴趣的:(《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个方法》要点回顾(四)第四章 协议与分类)