-
是什么?
通俗的讲,协议是一系列方法的列表,
注意: 只声明方法不实现它,实现的部分由遵守协议的那边完成。 -
怎么使用?
- 定义一个协议:
@protocol 协议名 <NSObject> ... 方法声明...@end
。#import <Foundation/Foundation.h> @protocol PeopleProtocol <NSObject> -(void)eat; //吃 -(void)drink; //喝 -(void)sleep; //睡 @end
- 让一个类去遵守这个协议.
People
类遵守PeopleProtocol
协议- 在
.h
文明中,声明协议#import XX.h"
- 遵守这个协议
<协议名称>
#import <Foundation/Foundation.h> #import "PeopleProtocol.h" @interface People : NSObject <PeopleProtocol> @end
- 在
- 在类的实现里,去实现协议里定义的方法.
@implementation People - (void)drink { NSLog(@"喝起来"); } - (void)eat { NSLog(@"吃起来"); } - (void)sleep { [self eat]; [self drink]; NSLog(@"吃了喝,喝了睡,真爽!"); }
- 使用
- (void)viewDidLoad { [super viewDidLoad]; People *pe = [[People alloc]init]; [pe sleep]; -- 协议的方法 }
- 定义一个协议:
特点:
- 一个类遵守了什么协议,就要实现这个协议规定的方法。
-
@required
修饰的方法是必须实现得。(默认得) -
@optional
修饰的方法是可实现,也可不实现得。
-
- 一个协议可以同时遵守多个协议。(多个协议直接用
,
隔开),也叫做扩展现有协议。@protocol StaffProtocol <NSObject,PeopleProtocol> @end
-
"实现协议的类" 需要实现所有协议的
@required
修饰的方法 -
协议跟继承的区别,
- 继承只能继承一个,
- 继承是单继承,协议可以是多协议.
- 协议与协议之间叫遵守. 类与类之间叫继承
-
"实现协议的类" 需要实现所有协议的
- 一个类可以遵守多个协议。(多个协议直接用
,
隔开)- 遵循单个协议
@interface XX () <UITableViewDelegate>
- 遵循多个协议
@interface XX ()<协议名1,协议名2>
- 遵循单个协议
- 同一个协议可以被多个类遵守。
如:Staff
和Boss
类都遵循了PeopleProtocol
协议。#import "PeopleProtocol.h" @interface Staff : NSObject <PeopleProtocol> #import "PeopleProtocol.h" @interface Boss : NSObject <PeopleProtocol>
- 基协议
<NSObject>
基类与其同名.且基类也遵守这个协议.
所有的自定义协议都必须直接或间接遵守这个基协议。 - 协议的提前声名
- 是什么?
@protocol 协议名;
注意: 有;
符号。
可放在协议里,也可放在类里
如:@protocol PeoPleTest;
- 特点 ?
仅仅是告诉这个类,有这个协议,但是协议里的内容不知道(方法有哪些,并不知道).
注意: 在"实现协议的类里面", 去实现协议里的方法,
必须在"类里面", 添加#import 协议名.h
- 有什么用?
- 类似于,在类里面的
@class
。 -
定义在使用/遵循的下面,则需要提前声明。
StaffProtocol
协议遵循PeopleProtocol
协议,
但是PeopleProtocol
还没有定义,所以就需先提前声明@protocol PeopleProtocol; //提前声明 - 定义在使用者这下面,则需要提前声明 -- 协议'StaffProtocol'遵循了'NSObject'协议和'PeopleProtocol'协议 @protocol StaffProtocol <NSObject,PeopleProtocol> //使用/遵循 PeopleProtocol协议 @end @protocol PeopleProtocol <NSObject> //定义'PeopleProtocol'协议 @end
- 类似于,在类里面的
- 是什么?
- 协议的内部定义
- 是什么?
类的内部,写协议。如:BossProtocol
协议,直接写在Boss
类里@protocol BossProtocol - (void)collectMoney;// 筹钱 @end @interface Boss : NSObject @end
- 什么情况下,使用内部协议?
此协议只是给某一个类/协议使用,则可以使用内部协议。
- 是什么?
- 限制对象类型
-
思路
- 假设: 老板想送奖品"MacBookPro"给优秀员工'八戒' ,有多种途径! (1. 快递奖品给"八戒"2.通过在一起的员工,转送给他....)
- 因存在多个对象,可以完成给"八戒"送"奖品"这事。
所以不能将对象的类型固定死。所以用id 类型
@property (nonatomic,weak) id delegate;
- 虽然老板有很多途径,可以将"奖品",送到"八戒"那。但是很多并不表示所有, 如: 随便叫个阿猫阿狗,肯定是无法送到!
- 所以肯定是将"奖品"交给能送到的人手里,叫他去送!
- 那怎样才能确保"他"是能送到的人呢?
- 遵循了协议的对象,就是能送到的人
@property (nonatomic,weak) id <CourierProtocol> delegate;
- 遵循了协议的对象,就是能送到的人
- 那怎样才能确保"他"是能送到的人呢?
- 所以说协议还有个功能,限制对象的类型。
-
示例代码
委托方: 就是委托别人干事的一方,指定协议的一方。#import "CourierProtocol.h" -- 引入协议文件 (带有方法) @protocol CourierProtocol; -- 声明协议(没有方法) @interface Boss : NSObject -- 注意没有'遵循协议' -- 任何对象,只要遵循了`CourierProtocol`协议的对象,都可以。 @property (nonatomic,weak) id <CourierProtocol> delegate; -(void)talkCourier; -- 喊人 @end
#import "CourierProtocol.h" @implementation Boss -(void)talkCourier{ -- 叫代理方去完成 -- 注意: 是[self.delegate ...], 不是[self ....] if([self. delegate respondsToSelector: @selector(sendStuff:)]){ [self.delegate sendStuff:@"奖品:MacBookPro" senderName:@"八戒" recipientName:@"你的Boss"]; } } @end
注意:
-
@protocol ...;
声明是没有方法得.后面用到方法还需要#import "XX.h"
- 上面示例中,在
.h
文件中有些引入协议#import "XX.h"
,就不需要@protocol ...;
声明。 - 如果在 "类的内部定义了协议",那么就不用写引入协议
#import "XX.h"
。 -
委托方在调用代理协议的方法时,要判断代理方是否实现了此方法(
respondsToSelector:
)
否则报错 NSInvalidArgumentException
代理方: 接受委托的一方;具体做事的,实现协议的一方。
#import "CourierProtocol.h" @interface Courier()<CourierProtocol> @end @implementation Courier - (void)sendStuff:(NSString *)stuffName senderName:(NSString *)senderName recipientName:(NSString *)name{ NSLog(@"'%@'收到了,来自'%@'寄来的'%@'",senderName,name,stuffName); } @end
协议: 代理方做事的守则,也就是代理方需要实现方法的申明。
#import <Foundation/Foundation.h> @protocol CourierProtocol <NSObject> - (void)sendStuff:(NSString *)stuffName senderName:(NSString *)senderName recipientName:(NSString *)name; //送东西 @end
使用
- (void)viewDidLoad { [super viewDidLoad]; Boss *boss =[[Boss alloc]init]; -- Courier * courier = [[Courier alloc]init]; -- 快递员 -- boss.delegate = courier; Staff * staff = [[Staff alloc]init]; -- 员工 boss.delegate = staff; [boss talkCourier]; }
-
-
有什么用?
1.降低耦合.
2.提高扩展性.
-
注意:
- 协议没有父类,并且不能定义成员变量,且没有属性。
- 协议里的方法,都是声名,没有实现。
- 协议是无类的(classless),任何类都可以遵守某项协议
-
子类拥有父类协议的所有方法
因为子类拥有父类的所有行为和方法。
如果一个类遵守某项协议,那么它的子类也遵守该协议! -
协议的命名规范 : 名称+delegate, 如:
UIScrollViewDelegate
。
也可以看看
- delegate - 代理基础01
- delegate - 代理基础02
- delegate - 代理基础03
- 没有协议的代理-简单实现
- 代理设计模型-自定义
- delegate - ScrollView01
来自于哪里?
- iOS-MJ-UI基础-大神班/临散知识点/protocol -协议基础-01
网友评论