网络百科转载iOS

华山论剑之浅谈iOS的 target - action设计模式

2016-03-07  本文已影响1279人  神经骚栋

当我们觉得一件事情是理所当然的时候,那正是我们失去它的时候.

</b>

target - action设计模式 和 代理模式 以及Bolck 不管是哪一个,都是我们在编程过程中比较常用的,但是真正有多少人还记得他们的实现原理的?今天我就浅谈一下target - action设计模式 和 代理模式 以及Bolck 这三个模块.在谈之前,我们先看一张搞笑的图片,让我们对三种模式有个初步的了解.

设计模式

</br>

target - action设计模式


target - action设计模式 是一种比较常见的设计模式,比如我们在用button的时候,给button添加一个事件,我们就用到了target - action设计模式.现在我们就用target - action设计模式 做一个button,还原button的设计原理,当然了 我们还要加上tap手势.

</b>

现在我们在我们的.tapView.h中做两个属性 一个target属性,另外一个是action属性,然后声明一个target - action方法.
#import <UIKit/UIKit.h>

@interface TapView : UIView
//目标
@property(weak,nonatomic)id target;
//行为
@property(assign,nonatomic)SEL action;

//自定义方法
-(void)addCustomtarget:(id)target andAction:(SEL)action;

@end

</b>

在tapView.m文件中我们要两个方法进行实现,一个是-(void)addCustomtarget:(id)target andAction:(SEL)action;另外一个就是-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;这个方法就是模拟button功能的方法.原理就是如果有一个执行者和一个执行者能做的方法,那么我们就让执行者执行那个方法.

#import "TapView.h"

@implementation TapView

//自定义方法
-(void)addCustomtarget:(id)target andAction:(SEL)action{

    _action = action;
    _target = target;
    
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    //当视图点击的时候,target去执行action的方法并把自己传过去.
    //首先代理不能是空,而且代理(代理是对象!)的类中有方法并且能传出过来.
    if (nil != _target && [[_target class] instancesRespondToSelector:_action]) {
        [_target performSelector:_action withObject:self];
     
    }
    
}

</br>

代理模式


代理模式是什么?代理模式就是制定一个执行者去做某件事情,是不是觉得跟target - action设计模式很相似?我们现在就对代理模式进行一下代码的尝试.

</b>

在.h文件中我们首先要声明一个协议,然后在协议中声明我们要实现的代理方法,然后我们要在这个类的声明一个代理的属性,这里我就做一个当我们点击我们的视图的时候就会改变的颜色.

#import <UIKit/UIKit.h>

@protocol TouchViewDelegate <NSObject>

-(void)changeViewColor:(UIColor *)color;

@end


@interface TouchView : UIView

//声明一个代理,这个代理遵守TouchViewDelegate协议,
@property(nonatomic,assign)id<TouchViewDelegate> delegate;

@end

</b>

在.m中,我们要对代理的方法进行调用一下,这里我传的是一个颜色.

#import "TouchView.h"

@implementation TouchView

//我们还是用touchesBegandian
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    if (nil != self.delegate && [self.delegate respondsToSelector:@selector(changeViewColor:)]) {
        
        //我们传一个颜色到我们的ViewController去.
        [self.delegate changeViewColor:[UIColor brownColor]];
        
    }
    
}

@end

</b>

然后我们看一下在ViewController.m中所要做的操作吧.还记得nil != self.delegate && [self.delegate respondsToSelector:@selector(changeViewColor:)]这句代码吗?意思还是当我们的代理人存在,并且他有代理方法,那么我们就让代理人实现代理方法.


#import "ViewController.h"

#import "TouchView.h"

//在这里ViewController 要遵守协议....
@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{

    //现在参数color是有值的,这是因为在TouchView那个页面传过来的.
    self.touchView.backgroundColor = color;


}



@end


</br>

Bolck


Bolck块在我们的编程过程中也是很常用的,它叫匿名函数,其实它不是函数,而是一个数据类型,就如同int,char一样,但是要给Bolck赋的值却是一个函数!!Bolck保存的是一个函数..当我们不懂的时候,是可以这样的理解的..当然,我们使用Bolck和代理模式很多时候是用于做传值使用的.

</br>

现在我们做一个OtherViewController 和ViewController两个控制器界面之间的传值,我们就使用Bolck来完成这件事情 ,首先我们在OtherViewController.h 声明一个Bolck的属性,当然了,我们需要先改一下名字,让我们的Bolck不是那么的难看.

#import <UIKit/UIKit.h>

//给block改名成MyBlock
typedef void(^MyBlock)(NSString *);


@interface OtherViewController : UIViewController

//MRC:block的语义设置是copy,把block从栈区拷贝到堆区.使用完之后,在dealloc内释放
//ARC:语义设置使用strong即可
@property(nonatomic,strong)MyBlock block;

@end

现在在我们的.m中进行如下的操作,我们有个输入框textField,当我们输入完成之后,我们点击一下页面返回到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


我们在ViewController中做了哪些操作呢?如下,我们需要声明一个OtherViewController的属性,然后给OtherViewController对象的block进行赋值.然后就是push页面了~


#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

现在我们用图说明一下block传值的实现原理.

block设计模式

</br>
</br>

target - action设计模式 和 代理模式 以及Bolck在编程过程中用的比较多,这里就做一下简单的介绍.希望大家能够喜欢这篇文章.

上一篇下一篇

猜你喜欢

热点阅读