當(dāng)我們覺得一件事情是理所當(dāng)然的時(shí)候,那正是我們失去它的時(shí)候.
target - action設(shè)計(jì)模式 和 代理模式 以及Bolck 不管是哪一個(gè),都是我們?cè)诰幊踢^程中比較常用的,但是真正有多少人還記得他們的實(shí)現(xiàn)原理的?今天我就淺談一下target - action設(shè)計(jì)模式 和 代理模式 以及Bolck 這三個(gè)模塊.在談之前,我們先看一張搞笑的圖片,讓我們對(duì)三種模式有個(gè)初步的了解.
target - action設(shè)計(jì)模式
target - action設(shè)計(jì)模式 是一種比較常見的設(shè)計(jì)模式,比如我們?cè)谟胋utton的時(shí)候,給button添加一個(gè)事件,我們就用到了target - action設(shè)計(jì)模式.現(xiàn)在我們就用target - action設(shè)計(jì)模式 做一個(gè)button,還原button的設(shè)計(jì)原理,當(dāng)然了 我們還要加上tap手勢(shì).
現(xiàn)在我們?cè)谖覀兊?tapView.h中做兩個(gè)屬性 一個(gè)target屬性,另外一個(gè)是action屬性,然后聲明一個(gè)target - action方法.
#import <UIKit/UIKit.h>
@interface TapView : UIView
//目標(biāo)
@property(weak,nonatomic)id target;
//行為
@property(assign,nonatomic)SEL action;
//自定義方法
-(void)addCustomtarget:(id)target andAction:(SEL)action;
@end
在tapView.m文件中我們要兩個(gè)方法進(jìn)行實(shí)現(xiàn),一個(gè)是-(void)addCustomtarget:(id)target andAction:(SEL)action;另外一個(gè)就是-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;這個(gè)方法就是模擬button功能的方法.原理就是如果有一個(gè)執(zhí)行者和一個(gè)執(zhí)行者能做的方法,那么我們就讓執(zhí)行者執(zhí)行那個(gè)方法.
#import "TapView.h"
@implementation TapView
//自定義方法
-(void)addCustomtarget:(id)target andAction:(SEL)action{
_action = action;
_target = target;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//當(dāng)視圖點(diǎn)擊的時(shí)候,target去執(zhí)行action的方法并把自己傳過去.
//首先代理不能是空,而且代理(代理是對(duì)象!)的類中有方法并且能傳出過來(lái).
if (nil != _target && [[_target class] instancesRespondToSelector:_action]) {
[_target performSelector:_action withObject:self];
}
}
代理模式
代理模式是什么?代理模式就是制定一個(gè)執(zhí)行者去做某件事情,是不是覺得跟target - action設(shè)計(jì)模式很相似?我們現(xiàn)在就對(duì)代理模式進(jìn)行一下代碼的嘗試.
在.h文件中我們首先要聲明一個(gè)協(xié)議,然后在協(xié)議中聲明我們要實(shí)現(xiàn)的代理方法,然后我們要在這個(gè)類的聲明一個(gè)代理的屬性,這里我就做一個(gè)當(dāng)我們點(diǎn)擊我們的視圖的時(shí)候就會(huì)改變的顏色.
#import <UIKit/UIKit.h>
@protocol TouchViewDelegate <NSObject>
-(void)changeViewColor:(UIColor *)color;
@end
@interface TouchView : UIView
//聲明一個(gè)代理,這個(gè)代理遵守TouchViewDelegate協(xié)議,
@property(nonatomic,assign)id<TouchViewDelegate> delegate;
@end
在.m中,我們要對(duì)代理的方法進(jìn)行調(diào)用一下,這里我傳的是一個(gè)顏色.
#import "TouchView.h"
@implementation TouchView
//我們還是用touchesBegandian
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
if (nil != self.delegate && [self.delegate respondsToSelector:@selector(changeViewColor:)]) {
//我們傳一個(gè)顏色到我們的ViewController去.
[self.delegate changeViewColor:[UIColor brownColor]];
}
}
@end
然后我們看一下在ViewController.m中所要做的操作吧.還記得nil != self.delegate && [self.delegate respondsToSelector:@selector(changeViewColor:)]
這句代碼嗎?意思還是當(dāng)我們的代理人存在,并且他有代理方法,那么我們就讓代理人實(shí)現(xiàn)代理方法.
#import "ViewController.h"
#import "TouchView.h"
//在這里ViewController 要遵守協(xié)議....
@interface ViewController ()<TouchViewDelegate>
@property(nonatomic,strong)TouchView *touchView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.touchView = [[TouchView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
self.touchView.backgroundColor = [UIColor redColor];
//指定touchView的代理為ViewController.即為本身~
self.touchView.delegate =self;
[self.view addSubview: self.touchView];
}
-(void)changeViewColor:(UIColor *)color{
//現(xiàn)在參數(shù)color是有值的,這是因?yàn)樵赥ouchView那個(gè)頁(yè)面?zhèn)鬟^來(lái)的.
self.touchView.backgroundColor = color;
}
@end
Bolck
Bolck塊在我們的編程過程中也是很常用的,它叫匿名函數(shù),其實(shí)它不是函數(shù),而是一個(gè)數(shù)據(jù)類型,就如同int,char一樣,但是要給Bolck賦的值卻是一個(gè)函數(shù)!!Bolck保存的是一個(gè)函數(shù)..當(dāng)我們不懂的時(shí)候,是可以這樣的理解的..當(dāng)然,我們使用Bolck和代理模式很多時(shí)候是用于做傳值使用的.
現(xiàn)在我們做一個(gè)OtherViewController 和ViewController兩個(gè)控制器界面之間的傳值,我們就使用Bolck來(lái)完成這件事情 ,首先我們?cè)贠therViewController.h 聲明一個(gè)Bolck的屬性,當(dāng)然了,我們需要先改一下名字,讓我們的Bolck不是那么的難看.
#import <UIKit/UIKit.h>
//給block改名成MyBlock
typedef void(^MyBlock)(NSString *);
@interface OtherViewController : UIViewController
//MRC:block的語(yǔ)義設(shè)置是copy,把block從棧區(qū)拷貝到堆區(qū).使用完之后,在dealloc內(nèi)釋放
//ARC:語(yǔ)義設(shè)置使用strong即可
@property(nonatomic,strong)MyBlock block;
@end
現(xiàn)在在我們的.m中進(jìn)行如下的操作,我們有個(gè)輸入框textField,當(dāng)我們輸入完成之后,我們點(diǎn)擊一下頁(yè)面返回到ViewController 然后把值傳給ViewController.
#import "OtherViewController.h"
@interface OtherViewController ()
@property(nonatomic,strong)UITextField *textField;
@end
@implementation OtherViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.textField = [[UITextField alloc]initWithFrame:CGRectMake(0, 100, 414, 40)];
self.textField.backgroundColor = [UIColor lightGrayColor];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview: self.textField];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.block(_textField.text);
[self.navigationController popViewControllerAnimated:YES];
}
@end
我們?cè)赩iewController中做了哪些操作呢?如下,我們需要聲明一個(gè)OtherViewController的屬性,然后給OtherViewController對(duì)象的block進(jìn)行賦值.然后就是push頁(yè)面了~
#import "ViewController.h"
#import "OtherViewController.h"
@interface ViewController ()
@property(nonatomic,strong)OtherViewController *otherVC;
@property(nonatomic,strong)UILabel *label;
@end
@implementation ViewController
- (void)viewDidLoad {
self.view.backgroundColor = [UIColor whiteColor];
self.label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 414, 40)];
self.label.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.label];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.otherVC = [[OtherViewController alloc]init];
__weak typeof(self)weak = self;
//給block賦值~
self.otherVC.block = ^(NSString *string){
weak.label.text = string;
};
[self.navigationController pushViewController:_otherVC animated:YES];
}
@end
現(xiàn)在我們用圖說明一下block傳值的實(shí)現(xiàn)原理.