OC 协议 (protocol)&代理设计模式

2,016 阅读4分钟
  • 一个Protocol是由一系列的方法声明组成的

  • 类遵守协议

    • 一个类可以遵守1个或多个协议
    • 任何类只要遵守了Protocol,就相当于拥有了Protocol的所有方法声明
  • 注意

    • 协议不能声明成员变量,不能写实现
    • 只要父类遵守了某个协议,那么子类也遵守
    • 协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一份协议中的方法声明
@interface 类名 : 父类 <协议名称1, 协议名称2,…>
@end

基协议

  • NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它

  • 还有名字也叫NSObject的协议,它是一个基协议,最根本最基本的协议

  • NSObject协议中声明很多最基本的方法

    • description
    • retain
    • release
  • 建议每个新的协议都要遵守NSObject协议

@protocol SportProtocol <NSObject> // 基协议

@end

关键字

  • 协议中有2个关键字可以控制方法是否要实现(默认是@required,在大多数情况下,用途在于程序员之间的交流)

    • @required:这个方法必须要实现(若不实现,编译器会发出警告)
    • @optional:这个方法不一定要实现

代理设计模式

  • 代理设计模式的场合:

    • 当对象A发生了一些行为,想告知对象B(让对象B成为对象A的代理对象)
    • 对象B想监听对象A的一些行为(让对象B成为对象A的代理对象)
    • 当对象A无法处理某些行为的时候,想让对象B帮忙处理(让对象B成为对象A的代理对象)

举例:婴儿与保姆

// 协议
//1.一般情况下, 当前协议属于谁, 我们就将协议定义到谁的头文件中

#import <Foundation/Foundation.h>
@class Baby;
//2.协议的名称一般以它属于的那个类的类名开头, 后面跟上protocol或者delegate
@protocol BabyProtocol <NSObject>
//3.协议中的方法名称一般以协议的名称protocol之前的作为开头
//这里不太准确
//4.一般情况下协议中的方法会将触发该协议的对象传递出去
- (void)feedWithBaby:(Baby *)baby;
- (void)hypnosisWithBaby:(Baby *)baby;
@end

//#import "BabyProtocol.h"
@interface Baby : NSObject
// 食量
@property (nonatomic, assign) int food;
// 睡意
@property (nonatomic, assign) int drowsiness;
// 饿
- (void)hungry;
// 睡意
- (void)sleepy;
//可以将协议写在数据类型的右边, 明确的标注如果想给该变量赋值, 那么该对象必须遵守某个协议
//id,遵守该协议的对象属性可以更换
//5.一般情况下一个类中的代理属于的名称叫做 delegate
//这里方便理解
@property (nonatomic, strong) id<BabyProtocol> nanny;
@end

@implementation Baby

- (void)hungry
{
    self.food -= 5;
    NSLog(@"婴儿饿了");
    // 通知保姆
    //注意: 虽然在接受某一个对象的时候, 对这个对象进行了类型限定(限定它必须实现某个协议), 但是并不意味着这个对象就真正的实现了该方法. 所以每次在调用对象的协议方法时应该进行一次验证
    if ([self.nanny respondsToSelector:@selector(feedWithBaby:)]) {
        [self.nanny feedWithBaby:self];
    }
}

- (void)sleepy
{
    self.drowsiness += 5;
    NSLog(@"婴儿困了");
    // 通知保姆
    if ([self.nanny respondsToSelector:@selector(hypnosisWithBaby:)]) {
        [self.nanny hypnosisWithBaby:self];
    }
}
@end
//保姆
//当某一个类要成为另外一个类的代理的时候, 
//一般情况下在.h中用@protocol 协议名称;告诉当前类 这是一个协议.
//在.m中用#import真正的导入一个协议的声明

@protocol PersonProtocol;
@interface Nanny : NSObject <BabyProtocol>
@end
#import "Baby.h"
@implementation Nanny

- (void)feedWithBaby:(Baby *)baby
{
    baby.food += 10;
    NSLog(@"给婴儿喂奶, 现在的食量是%i", baby.food);
}

- (void)hypnosisWithBaby:(Baby *)baby
{
    baby.drowsiness += 10;
    NSLog(@"哄婴儿睡觉, 现在的睡意是%i", baby.drowsiness);
}
@end

协议的编写规范:

 1.一般情况下, 当前协议属于谁, 我们就将协议定义到谁的头文件中

 2.协议的名称一般以它属于的那个类的类名开头, 后面跟上protocol或者delegate

 3.协议中的方法名称一般以协议的名称protocol之前的作为开头

 4.一般情况下协议中的方法会将触发该协议的对象传递出去

 5.一般情况下一个类中的代理属于的名称叫做 delegate    6.当某一个类要成为另外一个类的代理的时候, 

   一般情况下在.h中用@protocol 协议名称;告诉当前类 这是一个协议.

    在.m中用#import真正的导入一个协议的声明