Block很简单,就像delegate的简化版

代理设计模式对于iOS开发的人来讲确定很熟悉了,代理delegate就是委托另外一个对象来帮忙完成一件事情,为何要委托别人来作呢,这实际上是MVC设计模式中的模块分工问题,例如View对象它只负责显示界面,而不须要进行数据的管理,数据的管理和逻辑是Controller的责任,因此此时View就应该将这个功能委托给Controller去实现,固然你做为码农强行让View处理数据逻辑的任务,也不是不行,只是这就违背了MVC设计模式,项目小还好,随着功能的扩展,咱们就会发现越写越难写;还有一种状况,就是这件事情作不到,只能委托给其余对象来作了,下面的例子中我会说明这种状况。python

下面的代码我想实现一个简单的功能,场景描述以下:TableView上面有多个CustomTableViewCell,cell上面显示的是文字信息和一个详情Button,点击button之后push到一个新的页面。为何说这个场景用到了代理delegate?由于button是在自定义的CustomTableViewCell上面,而cell没有能力实现push的功能,由于push到新页面的代码是这样的,ios

[self.navigationController pushViewController...];git

因此这时候CustomTableViewCell就要委托它所在的Controller去作这件事情了。github

按照个人编码习惯,我喜欢把委托的协议写在提出委托申请的类的头文件里面,如今的场景中是CustomTableViewCell提出了委托申请,下面是简单的代码,设计模式

@protocol CustomCellDelegate <NSObject>服务器

- (void)pushToNewPage;ide

@end 函数


@interface CustomTableViewCell : UITableViewCell学习

@property(nonatomic, assign) id<CustomCellDelegate> delegate;编码

@property (nonatomic, strong) UILabel *text1Label;

@property(nonatomic,strong) UIButton *detailBtn;

@end

上面的代码在CustomTableViewCell.h中定义了一个协议CustomCellDelegate,它有一个须要实现的pushToNewPage方法,而后还要写一个属性修饰符为assign、名为delegate的property,之因此使用assign是由于这涉及到内存管理的东西,之后的博客中我会专门说明缘由。

接下来在CustomTableViewCell.m中编写Button点击代码,

[self.detailBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];

对应的btnClicked方法以下,

- (void)btnClicked:(UIButton *)btn

{

    if (self.delegate && [self.delegaterespondsToSelector:@selector(pushToNewPage)]) {

        [self.delegate pushToNewPage];

    }

}

上面代码中的判断条件最好是写上,由于这是判断self.delegate是否为空,以及实现CustomCellDelegate协议的Controller是否也实现了其中的pushToNewPage方法。

接下来就是受到委托申请的类,这里是对应CustomTableViewCell所在的ViewController,它首先要实现CustomCellDelegate协议,而后要实现其中的pushToNewPage方法,还有一点不能忘记的就是要设置CustomTableViewCell对象cell的delegate等于self,不少状况下可能忘了写cell.delegate = self;致使遇到问题不知云里雾里。下面的关键代码都是在ViewController.m中,

首先是服从CumtomCellDelegate协议,这个你们确定都知道,就像不少系统的协议,例如UIAlertViewDelegate、UITextFieldDelegate、UITableViewDelegate、UITableViewDatasource同样。

@interface ViewController ()<CustomCellDelegate>

@property (nonatomic, strong) NSArray *textArray;


@end

而后是实现CustomCellDelegate协议中的pushToNewPage方法,

- (void)pushToNewPage

{

    DetailViewController*detailVC = [[DetailViewController alloc] init];

    [self.navigationController pushViewController:detailVC animated:YES];

}

还有一个步骤最容易被忘记,就是设置CumtomTableViewCell对象cell的delegate,以下代码,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *simpleIdentify = @"CustomCellIdentify";

    CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleIdentify];

    if (cell == nil) {

        cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleIdentify];

    }

    //下面代码很关键

    cell.delegate = self;

    cell.text1Label.text = [self.textArray objectAtIndex:indexPath.row];

    return cell;

}

经过cell.delegate = self;确保了CustomTableViewCell.m的判断语句if(self.delegate && ...){}中得self.delegate不为空,此时的self.delegate其实就是ViewController,cell对象委托了ViewController实现pushToNewPage方法。这个简单的场景描述了使用代理的一种状况,就是CustomTableViewCell没有能力实现pushViewController的功能,因此委托ViewController来实现。

代码在github能够下载。

有什么错误,还请你们指正。

----------------------------------------------下面是block的内容----------------------------------------------------

Block是一个C语言的特性,就像群里有人说的,它就是C语言的函数指针,在使用中最多的就是进行函数回调或者事件传递,好比发送数据到服务器,等待服务器反馈是成功仍是失败,此时block就派上用场了,这个功能的实现也可用使用代理,这么说的话,感受block是否是有点像代理了呢?

我以前接触block,都是使用它做为函数参数,当时感受不是很理解。如今在项目中,不少时候block做为property,这样更加简单直接,想一想,其实property不就是定义的合成存储的变量嘛,而block做为函数参数也是定义的变量,因此做为函数参数或者做为property本质没有区别。

看一看别人总结的block的语法吧,http://fuckingblocksyntax.com,这个连接亮了,fucking block syntax,操蛋的block语法啊。block有以下几种使用状况,

一、做为一个本地变量(local variable)

returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};

二、做为@property

@property (nonatomic, copy) returnType (^blockName)(parameterTypes);

三、做为方法的参数(method parameter)

- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;

四、做为方法参数的时候被调用

[someObject someMethodThatTakesABlock: ^returnType (parameters) {...}];

五、使用typedef来定义block,能够事半功倍

typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};

上面我也只是复制粘贴了一下,接下来仍是实现点击CustomTableViewCell上面的Button实现页面跳转的功能,我以前不止一次的类比block就像delegate,这边我也是思惟惯性,下面的内容我就当block为代理,一些用词描述仍是跟delegate差很少。首先,在提出委托申请的CustomTableViewCell中定义block的property,

@interface CustomTableViewCell : UITableViewCell

@property (nonatomic, strong) UILabel *text1Label;

@property (nonatomic, strong) UIButton *detailBtn;


//下面的定义,请看官们对比一下

/*delegate的定义 我没有删除,由于你们能够类比了看下*/

@property (nonatomic, assign) id<CustomCellDelegate> delegate;

/*这里定义了ButtonBlock*/

@property (nonatomic, copy) void (^ButtonBlock)();

@end

这里用copy属性来修饰ButtonBlock property,这个缘由,我会在之后的博客中做专门的解释。

接下来在CustomTableViewCell中给它上面的detailBtn绑定点击方法,

[self.detailBtn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];

而后是btnClicked方法的细节,我把delegate的内容也没有删除,就是给各位比较一下block和delegate的功能和语法的类似性,

- (void)btnClicked:(UIButton *)btn

{

    //这是以前的delegate

    if (self.delegate && [self.delegate respondsToSelector:@selector(pushToNewPage)]) {

        [self.delegate pushToNewPage];

    }

    

    //这是如今咱们要说的block    

    if (ButtonBlock) {

        ButtonBlock();

    }

}

下面是一个关键性的地方,在ViewController2中设置其CustomTableViewCell的cell对象的ButtonBlock,也就是给它赋值,此处我仍是保留了cell.delegate = self;代码,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    NSString *blockIdentify = @"BlockIdentify";

    CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:blockIdentify];

    if (cell == nil) {

        cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:blockIdentify];

    }

    cell.text1Label.text = [self.textArray objectAtIndex:indexPath.row];

    //delegate的不可缺乏的代码,这里放在这儿只是为了给各位类比一下

    cell.delegate = self;

    

    //ButtonBlock不可缺乏的代码

    cell.ButtonBlock = ^{

        [self pushToNewPage2];

    };

    return cell;

}

之因此cell.ButtonBlock = ^{};赋值,是由于咱们咱们是这样定义ButtonBlock的,void (^ButtonBLock)(),表示无返回值无参数。

而后编写pushToNewPage2方法,

- (void)pushToNewPage2

{

    DetailViewController *detailVC = [[DetailViewController alloc] init];

    [self.navigationController pushViewController:detailVC animated:YES];

}

大家看这个方法是否是与CustomCellDelegate协议中的pushToNewPage方法相似。而后在回过头来类比同样,是否是block就是精简版的delegate,由于delegate设计模式要写协议CustomCellDelegate,还有容易遗漏cell.delegate = self;可是block使用的时候就简单多了。

最新的代码我已经更新到github,很是简单,有疑问或者有质疑的朋友能够下载看看。

另:本人也是ios开发菜鸟,对于不少的细节了解不够深刻,上面的代码使用arc编码,若是我写的有什么问题或者有什么缺陷的话,还请大神给我指正。

很但愿有各位开发者相互交流,提升技术,个人邮箱:zheniyerenrou@163.com。还有一个qq交流群188647173,有兴趣的能够加进来讨论讨论、学习学习,也但愿牛逼的大神到群里给咱们菜鸟指点指点。

相关文章
相关标签/搜索