假设我们需要达成的需求:在 View 文件中包含一个 UIButton 控件且包含 selector 方法,需求:在 Controller 中对其调用。

准备文件:

  • SpecificView.h & SpecificView.m
  • UIViewController.h & UIViewController.m

解决方法:

  • 通过暴露属性的方式来达到目的(这里就不谈了,自行百度
  • 采用代理模式。代理模式用大白话说就是:委托方让代理方代替自己执行一定的动作

代理模式:

首先,在 SpecificView.h 中声明 Delegate 代理:

@protocol ScuserLoginContainerDelegate <NSObject>
- (void)onBtnClick:(UIButton *)sender;
@end
@interface SpecificView : UIView
@property (nonatomic, weak)id<ScuserLoginContainerDelegate> delegate;
@end

Delegate 的声明方法如下:

@protocol 协议名称 <NSObject>
- (void)协议方法;

注意:在这里,务必使用 weak 修饰符,防止出现“循环引用”。

@propery (nonatomic, weak)id<协议名称> delegate;

然后,在 SpecificView.m 中实现相关方法:

@interface SpecificView ()
//声明在.m中的按钮对外部不可见
@property (strong, nonatomic) UIButton *myBtn;

@end

@implementation MyView
//初始化
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        _myBtn = [[UIButton alloc] initWithFrame:CGRectMake(140, 100, 100, 50)];
        _myBtn.backgroundColor = [UIColor redColor];
        //为按钮设置目标-动作,其中目标是self即包含该按钮的view自身,动作是有目标(view)提供的myBtnClick:方法
        [_myBtn addTarget:self
                   action:@selector(myBtnClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_myBtn];
    }
    
    return self;
}
// view 中按钮的事件
- (void)myBtnClick:(UIButton *)btn
{
    NSLog(@"Method in view");
    //在回调代理方法时,首先判断自身的代理是否实现了代理方法,否则会导致崩溃
    //如果自身代理实现了代理方法,在该方法中回调代理实现的具体的代理方法
    if ( [self.delegate respondsToSelector:@selector(onBtnClick:)] )
    {
        [self.delegate onBtnClick:btn];
    }
    else
    {
        NSLog(@"BtnClick: haven't found in delegate.");
    }
}
@end

接着,在 UIViewController.m 中遵循协议,创建 SpecificView 对象并且设置代理为 self ,在这里即是 UIViewController 。

SpecificView *container = [[SpecificView alloc]initWithFrame:self.view.bounds];
container.delegate = self;

最后,直接调用协议方法。

- (void)onBtnClick:(UIButton *)sender{
    //TODO 完成点击按钮后的方法
}

总结:采用代理模式能够实现 view 和 controller 之间的解耦。这是因为由于按钮事件是在 view 中绑定的,而不是在 controller 中绑定的,因此使用该 view 的类只需要实现相应的代理方法就可以定制按钮点击后的事件了,这也更加方便了 view 的复用,体现了 view 与 controller 解耦合的优势。

标签: none

添加新评论