• 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

  • 相关阅读:
    LeetCode Algorithm
    实现QObject与JavaScript通讯(基于QWebEngine + QWebChannel)
    Linux工具参考篇(网摘)
    GO 语言简介(网摘)
    Qt窗体引用window自带阴影边框效果
    无插件VIM编程技巧(网摘)
    ASP.NET 5基础之中间件
    ASP.NET Core 1.0基础之应用启动
    理解ASP.NET 5 Web Apps
    DNX 概览
  • 原文地址:https://www.cnblogs.com/Coder-GT/p/4869879.html
Copyright © 2020-2023  润新知