对于协议,感觉自己常用的就是 回调传值,再有就是面试的时候可能遇到过面试官提出的这样一个问题,iOS 如何实现多继承?
但是,经常在一些SDK或者第三方碰到一个单独的协议文件,有时候就有些迷糊,这样是干啥呢?就算遵守这个协议,那也没有实现触发方法啥的啊?
单独创建一个协议文件有什么意义呢?
我个人感觉就是用来解耦合的,虽然它单独创建了一个协议文件,但是它归根结底还是协议,只是单独创建出来,便于其他类来使用了而已
在segmentfault中我还看到过这样一段解答,感觉说的也非常好
协议是抽象的,只是描述不同事物的一些共性,比如说飞吧, 飞机和鸟都会飞,他们都实现了飞协议,但是他俩的实现方式是不一样的,那么飞这个协议是不是就应该单独定义呢?有一天可能人也会飞了,那么人去实现飞协议就可以了
通过协议提供匿名对象
在《编写高质量iOS与OS X代码的52个有效方法》的第28条中是这样来介绍的
- 用协议把自己所写的api之中的实现细节隐藏起来,将返回的对象设计为遵从此协议的纯id类型
- 接口背后有多个不同的实现类,而又不想指名具体哪个使用类
例:有三个不同的接口和模型,
- 班级学生模型 ClassStudentModel
- 年级学生模型 GradeStudentModel
- 学校学生模型 SchoolStudentModel
此时需要在个人中心页面中展示学生信息,内容可能来自于任意一个模型,这个时候在页面传递参数用哪个模型都不合适
两种方式解决
- 1、以前的话自己单独再创建一个模型,将传递的值一一赋值到新模型
- 2、通过协议提供匿名对象方式
普通方式
匿名对象方式
文件目录
文件目录.jpg
模型类
// 班级类
@interface ClassStudentModel : NSObject <PersonDelegate>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *age;
@property (nonatomic, strong) NSString *sex;
@end
// 年级类
@interface GradeStudentModel : NSObject <PersonDelegate>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *age;
@property (nonatomic, strong) NSString *sex;
@end
// 学校类
@interface SchoolStudentModel : NSObject <PersonDelegate>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *age;
@property (nonatomic, strong) NSString *sex;
@end
协议文件(注意,方法中的名称需要与模型名一致)
@protocol PersonDelegate <NSObject>
- (NSString *)name;
- (NSString *)age;
- (NSString *)sex;
@end
传值
- (void)presenViewController {
ClassStudentModel *classModel = [[ClassStudentModel alloc] init];
classModel.name = @"yanghuixue";
classModel.age = @"26";
classModel.sex = @"女";
// GradeStudentModel *gradeModel = [[GradeStudentModel alloc] init];
// gradeModel.name = @"qiangzi";
// gradeModel.age = @"25";
// gradeModel.sex = @"男";
PersonViewController *personVC = [[PersonViewController alloc] init];
id <PersonDelegate> delegate = classModel;
personVC.delegate = delegate;
[self presentViewController:personVC animated:YES completion:nil];
}
这里应该着重说一下,参数的类型为 id <PersonDelegate>,所以任何类型的对象都能充当这一参数,只要其遵循PersonDelegate即可,这也就是在前面图中展示,匿名对象传值方式的优点
展示
@interface PersonViewController : UIViewController
@property (nonatomic, strong) id <PersonDelegate> delegate;
@end
@implementation PersonViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"name = %@", self.delegate.name);
NSLog(@"age = %@", self.delegate.age);
NSLog(@"sex = %@", self.delegate.sex);
}
@end