在.h文件中添加兩個(gè)成員變量:
_target 和 _action
并且為這兩個(gè)成員聲明一個(gè)設(shè)置初值的方法:
- (void)addMyTarget:(id)target action:(SEL)action;
在.m文件中,當(dāng)進(jìn)去touchbegan時(shí),讓_target去執(zhí)行以下動(dòng)作:
[_target performSelector:_action withObject:self];
但是這個(gè)時(shí)候, _target是什么?_action是什么?
代理和targetAction的異同:
相同:首先他們都是讓controller來做一些事情.我們要明白一點(diǎn):我們舉的例子是觸摸事件發(fā)生的.但實(shí)際上這是view想要做什么事情的時(shí)候, 將邏輯部分交給controller來做的一種手段. 就算不是觸摸事件,一樣可以讓代理或者addtargetaction來做這些事情哦.
不同:實(shí)現(xiàn)方法不一樣,說不清楚,看例子吧:
targetAction: 代理:
1.創(chuàng)建RootViewController和RootView 代理相對(duì)來說就比較簡(jiǎn)單了, 你只需要明白代理是怎么回事就行了
2.現(xiàn)在我有一個(gè)視圖view的一些行為需要讓RootViewController來做,為了模擬這個(gè)主體,我再創(chuàng)建一個(gè)TouchView的視圖.處理這視圖的所有行為都放到RootViewController來做. 簡(jiǎn)單的說,你會(huì)描述,你就會(huì)寫.
3.在TouchView.h中做如下的事情:
3.1)添加兩個(gè)成員變量:
id _target; //目標(biāo). 讓誰來做這些事兒.
SEL _action; //實(shí)現(xiàn). 誰去實(shí)現(xiàn)這個(gè)方法.
3.2)為這兩個(gè)成員變量添加設(shè)置方法:
- (void)addMyTarget:(id)target action:(SEL)action;"
誰是委托人?誰是代理?委托人需要什么功能?代理需要能提供什么功能?
4.在TouchView.m中的Touch..began事件處理方法中,添加這樣一行代碼:
[_target performSelector:_action withObject:self];
解釋一下:通俗的講:就是讓_target去做_action這個(gè)動(dòng)作.
深層次一點(diǎn)的說法是,_target是一個(gè)對(duì)象的主體,_target賦值后的對(duì)象一定有執(zhí)行方法的能力.那么,首先,賦的值必須是一個(gè)對(duì)象.誰給_target賦值,誰就負(fù)責(zé)傳一個(gè)對(duì)象過來.但是你代碼寫在這里,誰能給你賦值?誰知道你在誰?怎么給你值?
perform是一個(gè)登記的機(jī)制, 我猜啊, 有一張方法字典表, 記錄了selector可以查找到的所有方法.當(dāng)然我這么說一點(diǎn)根據(jù)都沒有,我在瞎猜.先往下寫一點(diǎn),沒準(zhǔn)就明白了." 委托者是:TouchView 代理是RootViewController.
5.如果我們點(diǎn)擊了屏幕發(fā)生了事件(點(diǎn)在了TouchView中),那么會(huì)發(fā)生什么事情?
根據(jù)響應(yīng)者鏈規(guī)則1,我們找到了TouchView,發(fā)現(xiàn)TouchView中有處理方法(touch began).于是它就執(zhí)行了[_target performSelector:_action withObject:self];這段代碼….我靠,有controller毛事兒啊!
媽蛋,這performSelector肯定做了什么事情!" 委托人負(fù)責(zé)制定協(xié)議, 代理需要引入委托人的頭文件(引入類和協(xié)議)
這里簡(jiǎn)直就是一個(gè)深坑. 委托人需要自己調(diào)方法, 但是這個(gè)方法是代理提供的.
SEL:是一種數(shù)據(jù)類型,它對(duì)方法進(jìn)行了包裝(說的好聽),上面的_action的類型是SEL,也就是:@selector(fun)類型. 真正執(zhí)行方法的時(shí)候,實(shí)在委托人的方法中,(在委托人的方法中),給代理發(fā)送了一個(gè)代理的方法, 轉(zhuǎn)而代理去執(zhí)行了那個(gè)方法.
SEL是一個(gè)結(jié)構(gòu)體,它是對(duì)方法封裝后得到的,所以,里面不單單應(yīng)該有函數(shù)指針. 所以,這兩種模式,都使用到了一ID類型.通用類型指針.
我明白了!關(guān)鍵是:包裝的SEL類型數(shù)據(jù)它對(duì)應(yīng)相應(yīng)的方法地址,找到方法地址就可以調(diào)用方法 targetaction的id是作為一個(gè)替換的變量存在的.而委托人中的id<協(xié)議>類型指針,則是實(shí)實(shí)在在的指向了一個(gè)對(duì)象
"從整個(gè)ios的app流程來說,先走完RootViewController的Viewdidload方法, 那之前已經(jīng)實(shí)例化了一個(gè)TouchView的對(duì)象.里面已經(jīng)對(duì)這兩個(gè)_target和_action賦值了.另外,TouchView已經(jīng)是一個(gè)對(duì)象了,它當(dāng)然能調(diào)用方法.所以,當(dāng)發(fā)生點(diǎn)擊事件的時(shí)候,_tar和_action都已經(jīng)可以直接調(diào)用了.
在touchbegan方法中,[_target performSelector:_action withObject:self];變成了:
[RootViewController performSelector:@selector(touchViewAction:) withObject:TouchView];
這段代碼在哪兒執(zhí)行的呢?實(shí)在TouchView.m中的touchbegan中." id是所有對(duì)象類型的父指針,父類指針指向子類對(duì)象,這其實(shí)是一種多態(tài)現(xiàn)象.
"整個(gè)過程有點(diǎn)如下的意思:
我是TouchView類,我一會(huì)兒要接受觸摸事件,做出一個(gè)動(dòng)作, 我做動(dòng)作的格式是
[_target performSelector:_action withObject:self];
你們一會(huì)兒誰初始化我,實(shí)例化我的對(duì)象的時(shí)候, 一定要把_target和_action給我賦上值啊.到時(shí)候我根據(jù)你們的賦值,去你們的對(duì)象里找方法." "于是乎:委托人需要提供:
1)協(xié)議(用到了class),
2)委托人需要提供一個(gè)id類型的通用指針,用來指向代理(具體的對(duì)象)可以通過指向不同的代理,用相同的調(diào)用代碼執(zhí)行處不同的結(jié)果(這tm的就是多態(tài)啊).
3)調(diào)用代碼([self.delegate 方法],方法名相同但是因?yàn)閐elegate指向不同的對(duì)象,而每個(gè)對(duì)象都遵循實(shí)現(xiàn)這個(gè)方法的協(xié)議,所以他們能得到不同的結(jié)果, 在這里,只是一種結(jié)果, 是對(duì)代理協(xié)議模式的一種應(yīng)用,一種閹割的應(yīng)用方法."
相反, 代理 虱子多了不癢, 我只需要顯示的將子視圖的代理指針(id類型)指向自己,然后給你提供一個(gè)方法,就不管你了, 你什么時(shí)候需要執(zhí)行我的代碼,隨便來. 反正我也不會(huì)被你中斷.放馬過來..
在TouchView.h中
@interface TouchView : UIView
{
// 這兩個(gè)東西可以幫我們拆離代碼
// 第一步:
id _target; //目標(biāo). 讓誰來做這些事兒.
SEL _action; //實(shí)現(xiàn). 誰去實(shí)現(xiàn)這個(gè)方法.
}
// 提供一個(gè)借口,添加目標(biāo)和行動(dòng).
// 第二步:
- (void)addMyTarget:(id)target action:(SEL)action;
@end
在TouchView.m中
@implementation TouchView
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 第三步:
[_target performSelector:_action withObject:self];
}
- (void)addMyTarget:(id)target action:(SEL)action
{
_target = target;
_action = action;
}
@end
在RootViewController中:先實(shí)例化對(duì)象 ,再報(bào)備(為_target和_action賦值, 最后是action方法.
-(void)loadView
{
self.rv = [[[RootView alloc] initWithFrame:[UIScreen mainScreen].bounds]autorelease];
self.view = _rv;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 報(bào)備.
[self.rv.tv addMyTarget:self action:@selector(touchViewAction:)];
//self.rv.backgroundColor = [UIColor greenColor];
}
- (void)touchViewAction:(TouchView *)sender
{
NSLog(@"%@",sender); // 如果performselector不傳第二個(gè)參數(shù)withobject,那么這里的sender就不能用.
sender.backgroundColor =[UIColor colorWithRed:arc4random()%256/255.0 \
green:arc4random()%256/255.0 \
blue:arc4random()%256/255.0 \
alpha:1];