往常我们在自定义控件时,需要封装一些子控件。常常需要为其设置触发监听事件,但我们在定义控件的类中无法实现。为了解决此问题,我们利用了代理模式进行解决,主要步骤是:新建一个协议里面定义了实体类具体执行的方法。
然后封装了一个自定义控件类,在类里设置了一个必须遵循协议的代理属性,当触发子控件的监听事件时就在事件方法内调用自身的代理来完成事先无法确定的操作即让代理执行协议中的方法。 发现过程过于繁琐。
其实使用Block块也可以取代代理的这种操作,具体步骤如下:
新建工程,拉进一张图片和Masonry第三方适配框架。并新建pch文件,将框架的头文件导入:
最后的pch文件如下:
//
// PrefixHeader.pch
// Block块变量替换代理
//
// Created by apple on 15/10/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#ifndef Block________PrefixHeader_pch
#define Block________PrefixHeader_pch
#define WIDTH [UIScreen mainScreen].bounds.size.width
#define HEIGHT [UIScreen mainScreen].bounds.size.height
#import "Masonry.h"
#import "TestBlockView.h"
#import "ViewController2.h"
#endif
新建自定义控件如下所示:
TestBlockView.h
// TestBlockView.h
// Block块变量替换代理
//
// Created by apple on 15/10/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TestBlockView : UIView
typedef void (^TestBlock) (TestBlockView * testV);
@property (nonatomic, strong) UIImageView *imgv;
@property (nonatomic, strong) UILabel *lblDes;
@property (nonatomic, strong) TestBlock block;
-(id)initWithFrame:(CGRect)frame lblText:(NSString *) text imgNam:(NSString *)imgNam;
@end
TestBlockView.m
//
// TestBlockView.m
// Block块变量替换代理
//
// Created by apple on 15/10/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import "TestBlockView.h"
@implementation TestBlockView
-(id)initWithFrame:(CGRect)frame lblText:(NSString *) text imgNam:(NSString *)imgNam
{
if (self = [super initWithFrame:frame]) {
self.imgv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imgNam]];
self.lblDes = [[UILabel alloc] init];
self.lblDes.text = text;
[self addSubview:self.imgv];
[self addSubview:self.lblDes];
[self.imgv mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.and.right.equalTo(self);
make.top.equalTo(self);
make.bottom.equalTo(self).offset(-20);
}];
[self.lblDes mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.and.right.equalTo(self);
make.top.mas_equalTo(self.imgv.mas_bottom);
make.bottom.equalTo(self);
}];
UITapGestureRecognizer *recog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(TapEvent)];
recog.numberOfTapsRequired = 1;
recog.numberOfTouchesRequired = 1;
[self addGestureRecognizer:recog];
}
return self;
}
-(void)TapEvent
{
self.block(self);
}
@end
第一个控制器如下:
//
// ViewController.m
// Block块变量替换代理
//
// Created by apple on 15/10/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
TestBlockView * tv = [[TestBlockView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) lblText:@"Block测试" imgNam:@"1"];
// 在块内调用控制器对象相当于又retain了一次,为了避免循环引用必须用__weak
__weak typeof(self) weakSelf = self; // 等同于__weak UIViewController weakSelf = self;
tv.block = ^(TestBlockView *tbv){
ViewController2 *vc2 = [[ViewController2 alloc] init];
vc2.blockView = tbv;
[weakSelf presentViewController:vc2 animated:YES completion:nil];
};
tv.center = CGPointMake(WIDTH/2, HEIGHT/2);
[self.view addSubview:tv];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
点击空间后跳转的第二个控制器如下:
//
// ViewController2.h
// Block块变量替换代理
//
// Created by apple on 15/10/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController2 : UIViewController
@property (nonatomic, strong) TestBlockView *blockView;
@end
.m文件如下:
//
// ViewController2.m
// Block块变量替换代理
//
// Created by apple on 15/10/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import "ViewController2.h"
@interface ViewController2 ()
@end
@implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imgv = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
imgv.image = self.blockView.imgv.image;
[self.view addSubview:imgv];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
运行结果如下: