target/action设计模式

在写程序的时候,用了MVC将程序分层。那么就得在写程序的时候把对应的代码写在对应的层里。

target/action模式,就是用来解决这个问题的。也就是所谓的解耦合。程序里就应该做到“高聚合,低耦合”。

高聚合的意思,就是将属于自己的东西,都写在自己的层次里,尽量少的写在其他层次中。

低耦合的意思,是不同的层次之间,尽量少的关联,但不能不关联。

以下是target/action实现解耦合的流程:(只写关键代码)

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen] bounds]]autorelease];

    self.window.backgroundColor = [UIColor whiteColor];

    RootViewController *root = [[RootViewController alloc]init];

    self.window.rootViewController = root;

   

    [self.window makeKeyAndVisible];

    [root release];

    root = nil;

    return YES;

}

代理,将根视图设置为RootViewController的对象,不再使用自己的window。

RootViewController.m

 

#import "RootViewController.h"

#import "RootView.h"

#import "ButtonView.h"

#import "ColorView.h"

@interface RootViewController ()

@property(nonatomic,retain)RootView *rv;

@end

 

@implementation RootViewController

 

-(void)loadView{

    self.rv = [[[RootView alloc]initWithFrame:[[UIScreen mainScreen] bounds]]autorelease];

    self.view = _rv;

}

 

- (void)viewDidLoad {

    [super viewDidLoad];

    // 告诉buttonView target 是谁,action是谁。

    [self.rv.bv myAddTarget:self action:@selector(bvAction:)];

}

 

- (void)bvAction:(ButtonView *)sender{

    NSLog(@"123456");

    NSLog(@"%@",sender);

}

 

1、@property(nonatomic,retain)RootView *rv;将试图设置为试图控制器所对应的视图(也就是将RootView代替controller自己本身的视图self.view = _rv;)。

2、[self.rv.bv myAddTarget:self action:@selector(bvAction:)];

(1)rv为controller被替代的根视图

(2)bv是我们自己定义的一个视图(ButtonView)

(3)myAddTarget:self action:@selector(bvAction:)

是我们在ButtonView中定义的一个方法

(4)参数self是controller本身,将controller本身传过去

(5)参数@selector(bvAction:)是用方法选择器将bvAvtion方法传过去。

RootView.h

#import <UIKit/UIKit.h>

@class ButtonView;

@class ColorView;

@interface RootView : UIView

 

// bv 属性将要在controller中使用

@property(nonatomic,retain)ButtonView *bv;

@end

把视图ButtonView作为RootView的一个属性。

RootView.m

#import "RootView.h"

#import "ButtonView.h"

@implementation RootView

- (instancetype)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        [self p_setupView];

    }

    return self;

}

 

- (void)p_setupView{

    self.backgroundColor = [UIColor yellowColor];

   

    self.bv = [[[ButtonView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)]autorelease];

    self.bv.backgroundColor = [UIColor blueColor];

    [self addSubview:_bv];

}

@end

根视图,就是把那些视图都加在这个rootView上 。

ButtonView.h

@font-face { font-family: "Courier New"; }@font-face { font-family: "宋体"; }@font-face { font-family: "Cambria Math"; }@font-face { font-family: "@宋体"; }@font-face { font-family: "Cambria"; }@font-face { font-family: "Heiti SC Light"; }@font-face { font-family: "@Heiti SC Light"; }p.MsoNormal, li.MsoNormal, div.MsoNormal { margin: 0cm 0cm 0.0001pt; text-align: justify; font-size: 12pt; font-family: Cambria; }.MsoChpDefault { font-family: Cambria; }div.WordSection1 { page: WordSection1; }

#import <UIKit/UIKit.h>

@interface ButtonView : UIView{

    // 目标实例变量

    id _target;

    // 事件实例变量

    // 方法选择器类型

    SEL _action;

}

// 添加目标和事件

- (void)myAddTarget:(id)target action:(SEL)action;

@end

 

1、我们自己定义的视图,定义了两个实例变量,target是id类型的,也就是能代表所有的类型,用来接收一个目标,这个目标是为了执行action中的方法的。action是用来接收传进来的我自己要实现的方法(这里是点击事件bvButtonAction)。

2、- (void)myAddTarget:(id)target action:(SEL)action;

声明一个方法用来把controller中的要执行action方法的对象,执行的方法action传进来。

ButtonView.m

 

#import "ButtonView.h"

@implementation ButtonView

// 添加目标和事件

- (void)myAddTarget:(id)target action:(SEL)action{

    _target = target;

    _action = action;

   

}

在我们真正 要布局的地方重写初始化方法,把对应的视图建出来。

注意,我们想实现的点击事件,不在这里,这里没有点击事件,因为点击事件是逻辑性的东西,就把它写在了控制器ViewController里。

具体流程如下:

1、从controller开始,重写loadView方法,把rootView初始化,并代替自己的视图(self.view),然后去到rootView中,在初始化rootView的时候,把ButtonView也初始化了,创建了一个ButtonView视图bv。

2、当把视图都创建完毕后,完成加载,会回到controller中,调用viewDidload方法。此时我们就要重写这个方法,在viewDidload方法里,我们写上

[self.rv.bv myAddTarget:self action:@selector(bvAction:)];

这个调用方法,也就是把Buttonview中声明的myAddTarget: action:方法放到这里来调用。就会把控制器自己和在控制器里定义的ButtonView的点击响应事件方法传回去给ButtonView。

3、在ButtonView中,就会完成两个实力变量_target 和_action赋值。

4、此时,viewDidload方法执行完毕,真正完成视图的加载。

5、点击视图时,触发touchesBegan方法,在这个方法里,

[_target performSelector:_action withObject:self];

这个才是我们真正让_target和 _action完成功能的语句。这个意思就是让_target

(这就是之前传进来了controler )去执行_action (也就是之前传进来的bvAction方法)self就是ButtonView自己,设置这个withObject的参数,就是为了controller中定义bvAction方法的时候,参数sender得到ButtonView对象。

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    NSLog(@"开始点击..");

    // 让target执行action方法

    [_target performSelector:_action withObject:self];

}

@end

原文地址:https://www.cnblogs.com/Coder-GT/p/4869879.html