華山論劍之淺談iOS的 target - action設(shè)計(jì)模式 和 代理模式 以及Bolck

當(dāng)我們覺得一件事情是理所當(dāng)然的時(shí)候,那正是我們失去它的時(shí)候.

target - action設(shè)計(jì)模式 和 代理模式 以及Bolck 不管是哪一個(gè),都是我們?cè)诰幊踢^程中比較常用的,但是真正有多少人還記得他們的實(shí)現(xiàn)原理的?今天我就淺談一下target - action設(shè)計(jì)模式 和 代理模式 以及Bolck 這三個(gè)模塊.在談之前,我們先看一張搞笑的圖片,讓我們對(duì)三種模式有個(gè)初步的了解.

設(shè)計(jì)模式


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)原理.

block設(shè)計(jì)模式


target - action設(shè)計(jì)模式 和 代理模式 以及Bolck在編程過程中用的比較多,這里就做一下簡(jiǎn)單的介紹.希望大家能夠喜歡這篇文章.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。