协议和代理

1.协议基本概念

什么是协议?

  • 其他语言有接口的概念,接口就是一堆方法的声明没有实现.
  • OC中没有接口的概念,OC中的接口就是协议.
  • 协议Protocol是由一系列的方法声明组成的

书写协议的格式?

格式:

@protocol 协议名称 <NSObject>
// 方法声明列表

@end

 

 

一个类怎么遵循协议?

 

类遵守协议格式:

@interface 类名 : 父类 <协议名称1, 协议名称2,…>

@end

注意:

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

协议和继承区别

  1. 继承之后默认就有实现, 而protocol只有声明没有实现
  2. 相同类型的类可以使用继承, 但是不同类型的类只能使用protocol
  3. protocol可以用于存储方法的声明, 可以将多个类中共同的方法抽取出来, 以后让这些类遵守协议即可

2.协议注意事项

什么是基协议?

  • 基协议:是基协议,是最根本最基本的协议,其中声明了很多最基本的方法。
  • 注意:建议每个新的协议都要遵守NSObject协议

协议有哪些注意事项?

  1. 协议只能声明方法, 不能声明属性
  2. 父类遵守了某个协议, 那么子类也会自动遵守这个协议
  3. 在OC中一个类可以遵守1个或多个协议 注意: OC中的类只能有一个父类, 也就是说OC只有单继承
  4. OC中的协议又可以遵守其它协议, 只要一个协议遵守了其它协议, 那么这个协议中就会自动包含其它协议的声明

协议中控制方法的能否实现的关键字是什么?各有什么作用?

  1. 注意: 如果没有使用任何关键字修饰协议中的方法, 那么该方法默认就是required的
  2. 注意: @required和@optional仅仅使用程序员之间交流, 并不能严格的控制某一个遵守该协议的类必须要实现该方法, 因为即便不是实现也不会报错, 只会报一个警告
  3. @required 如果协议中的方法是@required的, 要求遵守协议的类实现@required所修饰的方法,如果没有实现该方法, 那么会报一个警告
  4. @optional 如果协议中的方法是@optional的, 遵守协议的类可选择实现@optional所修饰的方法,如果没有实现该方法, 那么不会报警告

 

3.协议应用场景1-类型限定

问题1:什么是类型限定?

答:类型限定就是限定一个类必须遵守某个协议

问题2:类型限定的格式?

答: 数据类型<协议名称> 变量名

 

@property (nonatomic, strong) Wife<WifeCondition> *wife;

 

 

 

类型限定注意点

  1. 类型限定是写在数据类型的右边的
  2. 虽然在接受某一个对象的时候, 对这个对象进行了类型限定(限定它必须实现某个协议), 但是并不意味着这个对象就真正的实现了该方法. 所以每次在调用对象的协议方法时应该进行一次验证
if ([self.wife respondsToSelector:@selector(cooking)]) {

[self.wife cooking];
}

 

 

代理模式的应用场景?

1.当A对象想监听B对象的一些变化时, 可以使用代理设计模式 保姆想监听婴儿的变化, 那么保姆就可以成为婴儿的代理, 当婴儿发生变化之后保姆就可以监听到

2.当B对象发生一些事情, 想通知A对象的时候, 可以使用代理设计模式 婴儿想通知保姆, 那么就可以 让保姆成为婴儿的代理, 只要保姆成为婴儿的代理, 以后婴儿发生变化就可以通知保姆

3.当对象A无法处理某些行为的时候,想让对象B帮忙处理(让对象B成为对象A的代理对象) 婴儿无法自己吃东西, 也无法自己入睡, 所以可以让保姆帮忙处理. 只要让保姆成为婴儿的代理就可以帮婴儿喂它吃东西和哄他睡觉

 

用什么类型来接收遵守协议的代理对象?

使用id类型接收代理对象

// 如果使用id类型来接收保姆, 如果将来换保姆了, 婴儿类不用修改代码

@property (nonatomic, strong) id<BabyProtocol> nanny;

 

 

 

问题3:实现代理的有哪几步?(保姆照顾婴儿 吃饭 睡觉)

答:

婴儿类中

1.声明婴儿是一个类(将当前对象传出去) @class Baby;

2.定义代理协议,协议中声明代理要帮婴儿做的事 (只声明方法,将婴儿传给代理,让代理实现协议中方法,注意协议格式)

@protocol BabyDelegate <NSObject>

//喂婴儿吃饭
- (void)eat:(Baby *)baby;
//哄婴儿睡觉
- (void)sleep:(Baby *)baby;

@end

 

 

3.将代理作为属性,类型限定代理遵守协议

 

@property (nonatomic, weak) id <BabyDelegate> delegate;

 

 

 

4.声明方法,方法里调用代理,调用代理实现的协议方法,让代理帮婴儿吃饭,睡觉

//婴儿饿了要吃饭
- (void)hurgry;

//婴儿醒了要睡觉
- (void)wake;

 

 

5.实现调用代理者的方法

@implementation Baby

- (void)hurgry{

//    6.判断代理是否实现了协议中的方法
    if ([self.delegate respondsToSelector:@selector(eat:)]) {
        //7.如果代理实现了协议中的方法,就调用
        [self.delegate eat:self];
    }
}

- (void)wake{
    if ([self.delegate respondsToSelector:@selector(sleep:)]) {
        [self.delegate sleep:self];
    }
}
@end

 

 

代理类中

8.导入代理

 

@protocol BabyDelegate;

 

 

 

9.遵守代理

@interface Nurse : NSObject <BabyDelegate>

@end

 

 

10.实现协议中的方法,(喂婴儿,让婴儿吃饭,拿到婴儿才能给婴儿做事)

@implementation Nurse

- (void)eat:(Baby *)baby{
    baby.hurgryValue += 10;
    NSLog(@"喂婴儿吃饭!饥饿值:%lu", baby.hurgryValue);

}

- (void)sleep:(Baby *)baby{
    baby.sleepValue += 5;

NSLog(@"摇婴儿睡觉!疲劳值:%lu", baby.sleepValue);
}
@end

 

 

main函数中

int main(int argc, const char * argv[]) {
    @autoreleasepool {

//11.创建所需对象
        Baby *b = [[Baby alloc]init];
        Nurse *n = [[Nurse alloc]init];

//12.将代理对象作为接受代理者的代理
        //(让保姆作为婴儿的代理)
        b.delegate = n;

//设定婴儿初始饥饿值,疲劳值
        b.hurgryValue = -5;
        b.sleepValue = -5;

//13.接受代理者调用代理者的方法
        //(婴儿饿了,醒了,需要吃饭和哄一哄)
        [b hurgry];
        [b wake];
    }
    return 0;
}

 

5.代理设计模式练习及规范

协议的编写规范

  1. 一般情况下, 当前协议属于谁, 我们就将协议定义到谁的头文件中
  2. 协议的名称一般以它属于的那个类的类名开头, 后面跟上protocol或者delegate
  3. 协议中的方法名称一般以协议的名称protocol之前的作为开头
  4. 一般情况下协议中的方法会将触发该协议的对象传递出去
  5. 一般情况下一个类中的代理属于的名称叫做 delegate
  6. 当某一个类要成为另外一个类的代理的时候, 一般情况下在.h中用@protocol 协议名称;告诉当前类 这是一个协议. 在.m中用#import真正的导入一个协议的声明

 

posted @ 2015-11-26 15:46  a滴答  阅读(191)  评论(0编辑  收藏  举报