1.非正式协议概念
给NSObject或者NSObject的子类增加类别
2. 1)定义协议 (.h文件中)
2)采纳(采用)协议(ClassA.h中,类声明的时候采纳协议)
3)ClassA.m中 实现协议对应的方法
协议定义
@protocol协议名称 <NSObject> //默认遵守NSObject协议
采纳协议
一.类遵守协议(创建类的时候遵守某个或几个协议)
@interface类名:父类<协议名称>
@end
@interface类名:父类<协议名称1,协议名称2>
@end
二、协议遵守协议(一个协议可以遵守其他多个协议)
@protocol 协议名称<其他协议名称>
@end
@protocol 协议名称<其他协议名称1,其他协议名称2>
@end
2.baseProtocol.h中定义协议
#import <Foundation/Foundation.h>
@protocol baseProtocol <NSObject>
- (void)eat; //声明一些方法
- (void)run;
@end
//新建Person.h文件
#import"baseProtocol.h"
#import"workProtocol.h"
// 遵守协议
// 实现方法
// 当我们遵守了某个协议后,就相当于这个类有了协议中所有的 方法的声明
@interface Person:NSObject <baseProtocol,workProtocol>
@end
//Person.m文件
#import"Person.h"
@implement Person
- (void)eat{
}
- (void)run{
}
- (void)work{
}
@end
// 新建.m文件
#import"Person.h" //导入Person文件
Person *p = [Person new];
[p eat];
[p run];
[p work];
协议的关键字 @required / @optional
@protocol RunProtocol <NSObject>
// @required 修饰的必须要实现的方法
@required
- (void)run;
// @optional 修饰可以选择实现的方法
@optional
- (void)eat;
@end;
- protocol类型限制
id / instancetype 不同用法
houseHold.h
#import <Foundation/Foundation.h>
@protocol houseHold <NSObject>
@required; // 可省略
- (void)ZuoFan;
- (void)XiYiFu;
@optional;
- (void)goodJob;
@end;
main.m
#import "houseHold.h"
#import "Dog.h" // Dog类
#import "Girl.h"
Dog *d = [Dog new];
Girl *mm = [Girl new];
NSString *str = @"";
// 增加类型限制
// 第一种类型限制:给id类型增加限制
// id<houseHold> obj;
// 增加<houseHold>以后,表示obj只能赋值遵守了houseHold协议的对象
// id类型可以赋给任何值id obj = str id obj = d;
id <houseHold> obj = d;
//警告 obj没有实现对应的houseHold协议
//在d所在的Dog.h中导入头文件#import"houseHold.h"
遵守<houseHold>协议
// 修改后赋值语句为
id <houseHold> obj = d;
Dog.h 修改后
#import "Foundation/Foundation.h"
#import "houseHold.h"
@interface Dog: NSObject <houseHold>
@end
Girl.h
#import "Foundation/Foundation.h"
#import "houseHold.h"
@interface Girl: NSObject <houseHold>
@end
.m文件
// 第二种类型限制
// 表示,obj2赋值的时候,必须是Girl对象,并且遵守了houseHold协议
Girl<houseHold> *obj2 = mm;
第三种类型
新建caculatorProtocol协议 caculatorProtocol.h
#import <Foundation/Foundation.h>
@protocol caculatorProtocol
- (void)mod;
@end;
Girl.h
#import "Foundation/Foundation.h"
#import "houseHold.h"
#import "Dog.h"
#import "caculatorProtocol.h"
@interface Dog: NSObject <houseHold>
// 女孩养一条狗
// 要求这条狗,必须会算数
@property (nonatomic,strong) Dog<caculator> *dog;
@end
// main.m 文件中 第三种类型限制
Dog *d = [Dog new];
Girl *mm = [Girl new];
Girl<houseHold> *obj2 = mm;
obj2.dog = d;
Dog.h中添加遵守caculatorProtocol协议
#import <Foundation/Foundation.h>
#import "caculatorProtocol.h"
@interface Dog: NSObject<caculatorProtocol>
@end
id类型和instancetype的区别
1)instancetype只能作为函数或者方法的返回值
2)id能作为方法或者函数的返回值、参数类型、也用来定义变量
3)instancetype的好处- 能精确地限制返回值的具体类型
protocol代理设计模式引入
举例说明:婴儿和保姆之间有个协议,协议中写明保姆需要做什么事情,保姆遵守该协议,于是保姆就需要实现该协议中的条款成为代理人。婴儿饿了困了需要保姆照顾,使用类实现当前功能。
第一步,制定协议
照顾小孩的协议 (lookBabyProtocol)
- 喂奶 (feedBabyEat)
- 哄睡(HongBabySleep)
第二步,创建相关的类
1) 婴儿类
类名:Baby
属性:保姆、体力值、睡眠值
行为:
想吃东西(wantToEat) - 保姆喂奶
想睡觉(wantToSleep) - 保姆哄他睡觉
2) 保姆类 (需要遵守协议)
类名: Baomu
行为
lookBabyProtocol.h
#import <Foundation/Foundation.h>
@protocol lookBabyProtocol <NSObject>
// 喂婴儿吃饭
- (void)feedBabyEat;
// 哄婴儿睡觉
- (void)hongBabySleep;
@end
Baby.h
#import <Foundation/Foundation.h>
@class BaoMu;
#import "lookBabyProtocol"
@interface Baby : NSObject
// 保姆、体力值、睡眠值
@property (nonatomic, strong) BaoMu <lookBabyProtocol> *bm;
- (void)wantEat;
- (void)wantSleep;
@end
Baby.m
#import "Baby.h"
#import "BaoMu.h"
@implementation Baby
- (void)wantEat {
NSLog(@"婴儿在哭");
// 保姆要喂奶
[self.bm feedBabyEat];
}
- (void)wantSleep{
NSLog(@"婴儿在哭");
// 保姆要哄婴儿睡觉
[self.bm HongBabySleep];
}
@end
BaoMu.h
#import <Foundation/Foundation.h>
//保姆想成为baby的代理人,就必须遵守lookBabyProtocol协议
#import "lookBabyProtocol.h"
@interface BaoMu : NSObject <lookBabyProtocol>
@end
BaoMu.m
#import "BaoMu.h"
@implementation BaoMu
- (void) feedBabyEat{
NSLog(@"保姆正在喂婴儿吃东西");
}
- (void)HongBabySleep{
NSLog(@"保姆正在哄婴儿睡觉");
}
@end
main.m 文件
#import <Foundation/Foundation.h>
#import "BaoMu.h"
#import "Baby.h"
{
BaoMu *baomu = [BaoMu new];
Baby *baby = [Baby new];
baby.bm = baomu;
[baby wantEat];
[baby wantSleep];
}
为了体现出实现了协议功能将协议修改为
lookBabyProtocol.h
#import <Foundation/Foundation.h>
#import <Baby.h>
@protocol lookBabyProtocol <NSObject>
// 喂婴儿吃饭
- (void)feedBabyEat : (Baby *)baby;
// 哄婴儿睡觉
- (void)hongBabySleep : (Baby *)baby;
@end
Baby.m
#import "Baby.h"
#import "BaoMu.h"
@implementation Baby
- (void)wantEat {
NSLog(@"婴儿在哭...");
// 保姆要喂它吃
[self.bm feedBabyEat : self];
}
- (void)wantSleep {
NSLog(@"婴儿在哭");
[self.bm HongBabySleep : self];
}
@end
Baby.h
#import <Foundation/Foundation.h>
@class BaoMu;
#import "lookBabyProtocol"
@interface Baby : NSObject
@property (nonatomic, assign) float weight; //新增
@property (nonatomic, assign) float sleep;
// 保姆、体力值、睡眠值
@property (nonatomic, strong) BaoMu <lookBabyProtocol> *bm;
- (void)wantEat;
- (void)wantSleep;
@end
lookBabyProtocol.h
#import <Foundation/Foundation.h>
//替换导入Baby.h
@class Baby;
@protocol lookBabyProtocol : <NSObject>
// 喂婴儿吃饭
- (void)feedBabyEat : (Baby *)baby;
// 哄婴儿睡觉
- (void)HongBabySleep : (Baby *)baby;
BaoMu.m
#import "BaoMu.h"
#import "Baby.h"
@implementation BaoMu
- (void)feedBabyEat : (Baby *)baby {
baby.weight += 1;
NSLog(@"保姆正在喂婴儿吃东西,baby.weight = %.2f", baby.weight);
}
- (void)HongBabySleep : (Baby *)baby {
baby.sleep += 10;
NSLog(@"保姆正在哄婴儿睡觉, baby.sleep = %.2f", baby.sleep);
}
@end
main.m 文件
#import <Foundation/Foundation.h>
#import "BaoMu.h"
#import "Baby.h"
{
BaoMu *baomu = [BaoMu new];
Baby *baby = [Baby new];
baby.weight = 10;
baby.sleep = 20;
baby.bm = baomu;
[baby wantEat];
[baby wantSleep];
NSLog(@"%.2f ,%.2f ",baby.weight, baby.sleep);
}
6.应用:通过中介找房子
Student.h
#import <Foundation/Foundation.h>
#import "findHouseProtocol.h"
@interface Student : NSObject
- (void)needHouse;
@property (nonatomic, strong) id <findHouseProtocol> delegate;
@end
Student.m
#import <Student.h>
@implementation Student
- (void)needHouse {
NSLog(@"学生需要一个温暖的家");
[self.delegate findHouse];
}
findHouseProtocol.h
#import <Foundation/Foundation.h>
@protocol findHouseProtocol <NSObject>
- (void)findHouse;
@end
LinkHome.h 创建代理链接
#import <Foundation/Foundation.h>
#import "findHouseProtocol.h"
// 采纳协议
@interface LinkHome : NSObject <findHouseProtocol>
@end
LinkHome.m
#import "LinkHome.h"
@implementation LinkHome
- (void)findHouse {
NSLog(@"链家地产正在帮学生找房子");
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Student"
#import "LinkHome.h"
Student *stu = [Student new];
// 代理的类
LinkHome *linkHome = [LinkHome new];
stu.delegate = linkHome;
[stu needHouse];
// 代理类 LinkHome
// 代理对象 delega
// 协议 findHouseProtocol
// 协议内容 findHouse
WAWJ.h 新建代理类
#import <Foundation/Foundation.h>
#import "findHouseProtocol.h"
@interface : NSObject <findHouseProtocol>
@end
WAWJ.m
#import "WAWJ.h"
@implementation WAWJ
- (void)findHouse {
NSLog(@"我爱我家正在找房子");
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Student"
#import "LinkHome.h"
Student *stu = [Student new];
// 代理的类
LinkHome *linkHome = [LinkHome new];
WAWJ *wj = [WAWJ new];
stu.delegate = wj;
[stu needHouse];
代理模式概念
传入的对象,代替当前类完成了某个功能,成为代理模式
利用协议实现代理模式的主要思路为:
1.定义一个协议,里面声明代理类需要实现的方法列表,比如这里一个代理类需要实现的feedBaby 和 hongBabySleep方法
2.创建一个代理类(比如BaoMu),遵守上面的代理协议
3.在需要代理的类中(Baby),定义一个对象 类型为id 且遵守代理协议的成员变量(delegate)
4.在Baby类中调用成员变量delegate(代理)的方法,调用代理类的方法
5.main.m或其他使用Baby类的文件中,为Baby类的成员变量(代理类)赋值