【iOS】小蓝书学习(四)
小蓝书学习(四)
- 第23条:通过委托与数据源协议进行对象间通信
- 第24条:将类的实现代码分散到便于管理的数个分类之中
- 第25条:总是为第三方类的分类名加前缀
- 第26条:勿在分类中声明属性
- 第27条:使用“class-continuation分类”隐藏实现细节
第23条:通过委托与数据源协议进行对象间通信
对象之间经常需要相互通信,而通信方式有很多种。OC开发者广泛使用一种名叫委托模式的编程设计模式来实现对象间的通信,该模式的主旨是:定义一套接口,某对象若想要接受另一个对象的委托,则需遵从此接口,以便成为其“委托对象”。而这“另一个对象”则可以给其委托对象回传一些信息,也可以在发生相关事件时通知委托对象。
第24条:将类的实现代码分散到便于管理的数个分类之中
类中经常容易填满各种方法,而这些方法的代码则全部堆在一个巨大的实现文件中。在这个情况下,可以通过OC的“分类”机制,把类代码按逻辑划入几个分区中,这对开发与调试都有好处。下面通过个人信息这个类举例说明:
#import <Foundation/Foundation.h>
@interface EOCPerson : NSObject
@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;
@property (nonatomic, strong, readonly) NSArray *friends;
- (id)initWithFirstName: (NSString *)firstName andLastName:(NSString *)lastName;
/ * Friendship methods * /
- (void) addFriend:(EOCPerson *)person;
- (void) removeFriend:(EOCPerson *)person;
- (BOOL) isFriendsWith:(EOCPerson *)person;
/ * Work methods * /
- (void) performDaysWork;
- (void) takeVacationFromWork;
/ * Play methods * /
- (void) goToTheCinema;
- (void) goToSportsGame;
@end
如果使用分类机制把刚刚的类改成下面这样,将三个分类拆成三个文件:
EOCPerson + Friendship(.h/.m)
EOCPerson + Work(.h/.m)
EOCPerson + Play(.h/.m)
这样一来,我以下面的这个Friendship为例,举例说明一下其中应该怎么实现:
//EOCPerson + Friendship.h
#import "EOCPerson.h"
@interface EOCPerson (Friendship)
- (void) addFriend:(EOCPerson *)person;
- (void) removeFriend:(EOCPerson *)person;
- (void) isFriendsWith:(EOCPerson *)person;
@end
//EOCPerson + Friendship.m
#import "EOCPerson + Friendship.h"
@implementation EOCPerson (Friendship)
- (void) addFriend: (EOCPerson *)person {
/* ... */
}
- (void) removeFriend:(EOCPerson *)person {
/* ... */
}
- (BOOL) isFriendsWith:(EOCPerson *)person {
/* ... */
}
@end
即使类本身不是太大,我们也可以使用分类机制将其切割成几块,并把相应的代码归入不同的功能区中。
要点:
- 使用分类机制把类的实现代码划分成易于管理的小块。
- 将应该视为“私有”的方法归入名叫
Private
的分类中,以隐藏实现的细节。
第25条:总是为第三方类的分类名加前缀
要点:
- 向第三方类中添加分类,总应给其名称加上你专用的前缀。
- 想第三方类中添加分类时,总应给其中的方法名加上你专用的前缀。
第26条:勿在分类中声明属性
属性是封装数据的方式。尽管从技术上来看,分类里也可以声明属性,但这种做法还是要尽量避免。原因在于,除了“class-continuation
分类”之外,其它分类都无法向类中新增实例变量,故而,它们无法把实现属性所需的实例变量合成出来。
要点:
- 把封装数据所用的全部属性都定义在主接口里面
- 在“class- continuation分类”之外的其他分类中,可以定义存取方法,但尽量不要定义属性。
第27条:使用“class-continuation分类”隐藏实现细节
class-continuation
分类:
该分类与普通的分类不同,他必须定义在其所持续的那个类的实现文件中。其重要之处在于,这是唯一能声明实例变量的分类。与其他分类不同,该分类没有名字,举例说明:
@interface ECOPerson ()
@end
这样你就可以在其中定义你的私有方法和私有变量了,这样有什么好处呢?公共接口里本来就能定义实例变量。不过,把它们定义在“class-continuation分类”或“实现块”中可以将其隐藏起来,只供本类使用。
使用该类,我们可以将在public
中定义的只读属性的对象更改为可读写属性,这样做既可以让外界无法修改对象,又能在其内部按照需要管理其数据。这样,封装在类中的数据就由实例本身来控制,而外部代码则无法修改其值。
要点:
- 通过
class-continuation
分类向类中新增实例变量。 - 如果某属性在主接口中声明为“只读”,而类的内部又要用设置方法修改此属性,那么就在“
class-continuation
分类”中将其扩展为“可读写”。 - 把私有方法的原型声明在“
class-continuation
分类”里面。 - 若想使类所遵循的协议不为人所知,则可于“
class-continuation
分类”中声明。