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

在软件开发中,对象之间的通信是不可避免的。委托模式(Delegate Pattern)是一种常用的实现对象间通信的方式,也被称为代理模式。委托模式的核心思想是定义一套接口,使得一个对象可以将部分职责委托给另一个对象。在iOS开发中,常常通过委托模式实现数据的传递和事件的通知。

1. 委托模式概述

委托模式的主要步骤包括定义协议、声明委托属性、实现委托方法。需要注意的是,协议中的属性应该使用weak修饰符,以避免循环引用问题。在.m文件中遵循协议,实现委托方法。

@protocol MyDelegate

- (void)didReceiveData:(NSData *)data;

- (void)didTriggerEvent;

@end

@interface MyClass : NSObject

@property (nonatomic, weak) id delegate;

@end

@implementation MyClass

// 实现类的相关逻辑,调用委托方法

@end

2. 委托的两种情况

委托模式通常分为两种情况:数据和类之间的委托(数据源模式)以及对象将行为责任委托给另一个类。

在实现委托和数据源模式时,可以使用C语言中的“位段”数据类型,通过缓存方法的响应能力,提高程序的运行效率。

// 使用位段缓存方法的响应能力

struct {

unsigned int respondsToMethod1:1;

unsigned int respondsToMethod2:1;

// ... 其他方法

} delegateFlags;

3. 要点

委托模式为对象提供一套接口,用于将相关事件告知其他对象。将委托对象应该支持的接口定义成协议,并在协议中定义可能需要处理的事件。数据源模式适用于对象需要从另一个对象中获取数据的情况。

第24条:将类的实现代码分散到便于管理的数个分类中

Objective-C中的分类机制不仅用于补充类的功能,还可以用于规划代码,将类的实现代码分成多个易于管理的小块。通过分类,可以提高代码的可读性和维护性。

使用分类规划代码

// Friendship.h

@interface MyClass (Friendship)

- (void)friendshipMethod;

@end

// Work.h

@interface MyClass (Work)

- (void)workMethod;

@end

// Play.h

@interface MyClass (Play)

- (void)playMethod;

@end

在实际使用中,通过引入相应的头文件,可以使代码结构更加清晰。

利用分类管理私有方法

可以将私有方法放入单独的分类中,并使用特殊的前缀表示它们是私有方法。这样一方面可以遵循命名规则,另一方面可以在调试时清晰地识别私有方法。

要点

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

第25条:总是为第三方的分类名称加前缀

在使用分类机制向第三方类中添加功能时,为了避免方法名的冲突和覆盖,应始终为分类的名称和方法名加上特定的前缀。

为分类名称和方法名加前缀

// MyCategory.h

@interface NSString (MyCategory)

- (NSString *)my_customMethod;

@end

通过为分类和方法名添加前缀,可以避免与其他框架或库发生命名冲突,提高代码的稳定性和可维护性。

要点

向第三方类中添加分类时,总应为其名称和方法名加上专用的前缀。

第26条:勿在分类中声明属性

在Objective-C中,除了使用“class-continuation分类”之外,其他分类无法向类中新增实例变量。因此,在分类中声明属性可能导致意外覆盖已存在的属性,造成不可预知的行为。

不要在分类中声明属性

// 错误示例

@interface MyClass (MyCategory)

@property (nonatomic, strong) NSString *myProperty;

@end

如果需要在分类中实现属性,可以使用@dynamic关键字或消息转发机制,但这样的做法并不提倡。最好的实践是将属性定义在主接口中,因为分类的目的是扩展功能而非封装数据。

要点

将封装数据所用的全部属性都定义在主接口中。在“class-continuation分类”之外的其他分类中,可以定义存取方法,但尽量不要定义属性。

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

“class-continuation分类”是一种特殊的分类,它用于向类中新增实例变量和私有方法。通过使用“class-continuation分类”,可以将一些实现细节隐藏起来,只供本类使用。

1. class-continuation分类

// MyClass.m

@interface MyClass ()

@property (nonatomic, strong) NSString *privateProperty;

- (void)privateMethod;

@end

@implementation MyClass

// 类的实现代码

@end

在上述例子中,privateProperty和privateMethod只能在MyClass.m文件中使用,对外部不可见。这种方法可以避免暴露不必要的实

现细节。

2. class-continuation分类的合理用法

class-continuation分类不仅可以用于隐藏实例变量和私有方法,还可以将主接口中声明为“只读”的属性在分类中扩展为“可读写”,以便在类的内部设置其值。

// MyClass.h

@interface MyClass : NSObject

@property (nonatomic, readonly) NSString *readOnlyProperty;

@end

// MyClass.m

@interface MyClass ()

@property (nonatomic, readwrite) NSString *readOnlyProperty;

@end

@implementation MyClass

// 类的实现代码

@end

这种用法既保持了外部只读的特性,又允许内部进行读写操作。

3. 要点

通过“class-continuation分类”向类中新增实例变量。在“class-continuation分类”中可以将主接口中声明为“只读”的属性扩展为“可读写”。在“class-continuation分类”中声明私有方法和实例变量。

第28条:通过协议提供匿名对象

在软件开发中,有时需要处理不同实现类的情况,但不希望暴露具体的类名。使用协议提供匿名对象是一种解决方案,可以在一定程度上隐藏实际的对象类型。

1. 匿名对象

@protocol DatabaseHandler

- (void)connect;

- (void)queryData;

// ... 其他数据库相关方法

@end

@interface DatabaseManager : NSObject

- (id)getDatabaseHandler;

@end

在上述例子中,DatabaseManager通过协议提供了一个匿名对象,该对象具有处理数据库的能力。外部代码无需关心具体的实现类,只需要使用协议中定义的方法。

2. 要点

协议可在某种程度上提供匿名类型,通过协议的id类型来表示。使用匿名对象来隐藏具体类型,重要的是对象能够相应协议中定义的方法。

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。