iOS中有许多的设计模式,从今天开始我会陆续写一下关于设计模式的东西,都是自己的一理解,有什么错误或者说的不是很明白的,欢迎大家指正。
代理主要由三部分组成:协议,代理,委托。协议主要是用来指定双方可以做什么,必须做什么;代理:是指根据双方指定的协议完成委托方需要实现的功能;委托:是指根据指定的协议,指定代理去完成什么功能。下面我们具体介绍下代理
定义协议,协议指的是什么,协议就是为了规定代理双方的行为,协议的出现的形式一般是方法列表,或者是定义的服务于方法的属性,一般创建@protocol文件,用于多个类的使用。协议只能定义公用的一套接口,类似于一个约束代理双方的作用。但不能提供具体的实现方法,实现方法需要代理对象去实现。协议可以继承其他协议,并且可以继承多个协议,在iOS中对象是不支持多继承的,而协议可以多继承。通常我们在使用时有时会出现爆黄的情况,这是协议内部的判断方法检测到没有遵循协议。委托方:就是一个房子的主人,我需要你把这个房子装修成什么样,你需要按我的要求来,我就是委托方,而“你”在这里扮演的就是代理方,为我去做装修房子这件事情。当然在iOS中一个代理可以有多个委托方,而一个委托方也可以有多个代理,例如你在让他装修的时候也可以让别人给你买家具,而他在和你装修的时候也可以同时给别人装修。同时代理对象在很多情况下是可以复用的,可以创建多个代理对象为多个委托方服务。
下面我大概介绍下关于代理在内存方面的问题,我们经常用代理的都知道,我们在设置代理的属性的时候一般情况下用的都是weak,为什么会用到weak而不是我们经常用的strong类型呢?这是因为strong类型的指针会造成强引用,必定会影响一个对象的生命周期,这也就会形成循环引用,最终造成代理方和委托方两个对象都无法正常释放。这就是为什么要用weak的原因。
最后在介绍一种当下正慢慢流行使用的一种开发模式,就是简化控制器的代码量,这种模式就是类似于MVVM模式的一种开发模式,但是又不是MVVM模式,这种是怎么实现的呢?通过代理对象 来实现,我们可以将UITableView的delegate和DataSource单独拿出来,由一个代理对象类来进行控制,只将必须控制器处理的逻辑传递给控制器处理。例如以下代码(参考网络)
.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void (^selectCell) (NSIndexPath *indexPath);
// 代理对象(UITableView的协议需要声明在.h文件中,不然外界在使用的时候会报黄色警告,看起来不太舒服)
@interface TableViewDelegateObj : NSObject <UITableViewDelegate, UITableViewDataSource>
/**
* 创建代理对象实例,并将数据列表传进去
* 代理对象将消息传递出去,是通过block的方式向外传递消息的
* @return 返回实例对象
*/
+ (instancetype)createTableViewDelegateWithDataList:(NSArray *)dataList
selectBlock:(selectCell)selectBlock;
@end
.m文件
#import "TableViewDelegateObj.h"
@interface TableViewDelegateObj ()
@property (nonatomic, strong) NSArray *dataList;
@property (nonatomic, copy) selectCell selectBlock;
@end
@implementation TableViewDelegateObj
+ (instancetype)createTableViewDelegateWithDataList:(NSArray *)dataList
selectBlock:(selectCell)selectBlock {
return [[[self class] alloc] initTableViewDelegateWithDataList:dataList
selectBlock:selectBlock];
}
- (instancetype)initTableViewDelegateWithDataList:(NSArray *)dataList selectBlock:(selectCell)selectBlock {
self = [super init];
if (self) {
self.dataList = dataList;
self.selectBlock = selectBlock;
}
return self;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
cell.textLabel.text = self.dataList[indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataList.count;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
// 将点击事件通过block的方式传递出去
self.selectBlock(indexPath);
}
@end
控制器需要做的
self.tableDelegate = [TableViewDelegateObj createTableViewDelegateWithDataList:self.dataList
selectBlock:^(NSIndexPath *indexPath) {
NSLog(@"点击了%ld行cell", (long)indexPath.row);
}];
self.tableView.delegate = self.tableDelegate;
self.tableView.dataSource = self.tableDelegate;
这就是我关于代理的一些理解,希望对大家有一下帮助。
代理主要由三部分组成:协议,代理,委托。协议主要是用来指定双方可以做什么,必须做什么;代理:是指根据双方指定的协议完成委托方需要实现的功能;委托:是指根据指定的协议,指定代理去完成什么功能。下面我们具体介绍下代理
定义协议,协议指的是什么,协议就是为了规定代理双方的行为,协议的出现的形式一般是方法列表,或者是定义的服务于方法的属性,一般创建@protocol文件,用于多个类的使用。协议只能定义公用的一套接口,类似于一个约束代理双方的作用。但不能提供具体的实现方法,实现方法需要代理对象去实现。协议可以继承其他协议,并且可以继承多个协议,在iOS中对象是不支持多继承的,而协议可以多继承。通常我们在使用时有时会出现爆黄的情况,这是协议内部的判断方法检测到没有遵循协议。委托方:就是一个房子的主人,我需要你把这个房子装修成什么样,你需要按我的要求来,我就是委托方,而“你”在这里扮演的就是代理方,为我去做装修房子这件事情。当然在iOS中一个代理可以有多个委托方,而一个委托方也可以有多个代理,例如你在让他装修的时候也可以让别人给你买家具,而他在和你装修的时候也可以同时给别人装修。同时代理对象在很多情况下是可以复用的,可以创建多个代理对象为多个委托方服务。
下面我大概介绍下关于代理在内存方面的问题,我们经常用代理的都知道,我们在设置代理的属性的时候一般情况下用的都是weak,为什么会用到weak而不是我们经常用的strong类型呢?这是因为strong类型的指针会造成强引用,必定会影响一个对象的生命周期,这也就会形成循环引用,最终造成代理方和委托方两个对象都无法正常释放。这就是为什么要用weak的原因。
最后在介绍一种当下正慢慢流行使用的一种开发模式,就是简化控制器的代码量,这种模式就是类似于MVVM模式的一种开发模式,但是又不是MVVM模式,这种是怎么实现的呢?通过代理对象 来实现,我们可以将UITableView的delegate和DataSource单独拿出来,由一个代理对象类来进行控制,只将必须控制器处理的逻辑传递给控制器处理。例如以下代码(参考网络)
.h文件
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void (^selectCell) (NSIndexPath *indexPath);
// 代理对象(UITableView的协议需要声明在.h文件中,不然外界在使用的时候会报黄色警告,看起来不太舒服)
@interface TableViewDelegateObj : NSObject <UITableViewDelegate, UITableViewDataSource>
/**
* 创建代理对象实例,并将数据列表传进去
* 代理对象将消息传递出去,是通过block的方式向外传递消息的
* @return 返回实例对象
*/
+ (instancetype)createTableViewDelegateWithDataList:(NSArray *)dataList
selectBlock:(selectCell)selectBlock;
@end
.m文件
#import "TableViewDelegateObj.h"
@interface TableViewDelegateObj ()
@property (nonatomic, strong) NSArray *dataList;
@property (nonatomic, copy) selectCell selectBlock;
@end
@implementation TableViewDelegateObj
+ (instancetype)createTableViewDelegateWithDataList:(NSArray *)dataList
selectBlock:(selectCell)selectBlock {
return [[[self class] alloc] initTableViewDelegateWithDataList:dataList
selectBlock:selectBlock];
}
- (instancetype)initTableViewDelegateWithDataList:(NSArray *)dataList selectBlock:(selectCell)selectBlock {
self = [super init];
if (self) {
self.dataList = dataList;
self.selectBlock = selectBlock;
}
return self;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
cell.textLabel.text = self.dataList[indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataList.count;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
// 将点击事件通过block的方式传递出去
self.selectBlock(indexPath);
}
@end
控制器需要做的
self.tableDelegate = [TableViewDelegateObj createTableViewDelegateWithDataList:self.dataList
selectBlock:^(NSIndexPath *indexPath) {
NSLog(@"点击了%ld行cell", (long)indexPath.row);
}];
self.tableView.delegate = self.tableDelegate;
self.tableView.dataSource = self.tableDelegate;
这就是我关于代理的一些理解,希望对大家有一下帮助。