在开发的过程中,我们可能会碰到这样的情况,一个试图的内部的控件比较多,并且这个试图在多次出现,那我们就要考虑对其进行相应的封装,报漏外部数据模型,这样我们只需要在请求完毕数据,将数据赋值给相应模型,试图拿到数据对其内部的子控件数据进行赋值。
1,纯代码的封装
1.1,封装的步骤
1.在initWithFrame:方法中添加子控件,创建便利构造器方法,用于调用快速生成试图。
2.在LayoutSubviews方法设置子控件的尺寸,等相关的属性。
3.创建数据模型,通过重新set方法,实现对相应子控件显示数据的赋值。
1.2,代码编写注意点
对于初始化试图系统会先调用initWithFrame,然后再调用LayoutSubviews方法,无论创建对象调用的是init方法还是initWithFrame都会调用initWithFrame方法初始化对象,一般将子控件的初始化放在这个方法里面,针对子控件一般调用的是init方法,一般使用init方法生成试图的时候的frame value默认的为0,如果子控件的frame是依赖于父试图的,在这里设置就会出问题,但是子控件的尺寸不是依赖在这里进行设置也是可以显示的,但是在这设置的只会执行一次,当父视图的尺寸发生变化,子控件将不会发生随着变化,父视图的位置被修改就会走LayoutSubview方法,所以需要在这里进行子控件位置确定,并且在确定子控件位置的时候相对于父视图进行设置。使用纯代码不会走initWithCoder和wakeFromNib方法。
1.3,上代码
------ 自定控件view的.h文件------
#import#import "DataModel.h"
@interface CustomView : UIView
//数据模型
@property(strong, nonatomic) DataModel * dataModel;
//创建便利构造器,用于外部创建该自定义控件
+ (instancetype)customView;
@end
------ 自定控件view的.m文件------
#import "CustomView.h"
@interface CustomView()
{
//声明子控件
UILabel * _titleLable;
}
@end
@implementation CustomView
//构建便利构造器
+ (instancetype)customView
{
return [[self alloc] init];
}
//重写initWithFrame:方法,初始化控件
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//创建子控件
_titleLable = [[UILabel alloc] init];
[self addSubview:_titleLable];
}
return self;
}
//重写父类的layoutSubviews,当父控件的Frame发生变化的时候,相对于父控件布局的子控件的Frame也会随着相应的改变
- (void)layoutSubviews
{
[super layoutSubviews];
//设置子控件的Frame等
_titleLable.backgroundColor = [UIColor orangeColor];
_titleLable.textColor = [UIColor blackColor];
_titleLable.textAlignment = NSTextAlignmentCenter;
_titleLable.frame = CGRectMake(0, self.frame.size.height / 2 - 25, self.frame.size.width, 50);
}
//重写set方法,用于给子控件设置数据
- (void)setDataModel:(DataModel *)dataModel
{
//给成员变量赋值
_dataModel = dataModel;
//给子控件赋值
_titleLable.text = dataModel.name;
}
@end
------ 数据模型.h文件------
#import <Foundation/Foundation.h>
@interface DataModel : NSObject
//模型的数据
@property(strong, nonatomic) NSString * name;
@end
------ 数据模型.m文件------
#import "DataModel.h"
@implementation DataModel
@end
------ 调用自定控件.h文件------
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
------ 调用自定控件.m文件------
#import "ViewController.h"
#import "CustomView.h"
#import "DataModel.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"纯代码封装";
self.view.backgroundColor = [UIColor whiteColor];
[self addControls];
}
//添加控件方法
- (void)addControls
{
//创建数据模型
DataModel * dataModel = [[DataModel alloc] init];
dataModel.name = @"测试";
//生成自定义控件
CustomView * customer = [[CustomView alloc] init];
customer.frame = CGRectMake(50, self.view.frame.size.height/2 - 50, self.view.frame.size.width - 100, 100);
customer.dataModel =dataModel;
[self.view addSubview:customer];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
2,xib进行封装
2.1,封装的步骤
1.新建自定义控件类,如果没有xib,需要创建相应的xib与之绑定。
2.增加模型属性,通过重新set方法,实现对相应子控件显示数据的赋值。
2.2,代码编写注意点
1.加载xib后,系统会调用initWithCoder然后调用awakeFromNib,然后再调用LayoutSubviews方法,系统调用initWithCoder在进行xib进行解析,在这时,xib一些细节还没加载完毕,对于子控件的初始化一般放在awakeFromNib中,在对于子控件的位置和尺寸的设置也是一般放在LayoutSubviews方法中,这样父视图frame改变时,依赖其父视图的子视图的frame也会相应的变化。使用xib创建不会走initWithFrame方法。
2.当创建xib,拉控件,控件的尺寸无法改变的时候,需要将其size设置为Freefrom。
3.对于Uiview等绑定xib的时候,需要将点击左侧的File's Owner,设置他的类,做法:按住control从File's Owner往下拉到view上松开,点击view,
4.设置clss为相应的试图。
5.[[NSBundle mainBundle] loadNibNamed:@"ChildView" owner:self options:nil]在绑定的view的initWithCoder设置其为该xib的ower。
3,上代码
创建xib,自定义view和子控件
新建xib
自定义View的类并与类的属性连线
设置自定义View为可变的尺寸,View的背景色
关闭自动布局(Autolayout),才可以在layoutSubviews里重新设置Button的Frame值
------ 自定控件view的.h文件------
#import <UIKit/UIKit.h>
#import "DataModel.h"
@interface CustomView : UIView
//数据模型
@property(strong, nonatomic) DataModel * dataModel;
//创建便利构造器,用于外部创建该自定义控件
+ (instancetype)customView;
@end
------ 自定控件view的.m文件------
#import "CustomView.h"
@interface CustomView()
//声明子控件
@property (weak, nonatomic) IBOutlet UILabel *titleLable;
@end
@implementation CustomView
//构建便利构造器
+ (instancetype)customView
{
CustomView *view = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject];
return view;
}
//重写initWithCoder:方法,初始化控件
- (instancetype)initWithCoder:(NSCoder *)coder{
self = [super initWithCoder:coder];
if (self) {
}
return self;
}
//重写父类的layoutSubviews,当父控件的Frame发生变化的时候,相对于父控件布局的子控件的Frame也会随着相应的改变
- (void)layoutSubviews
{
[super layoutSubviews];
//设置子控件的Frame等
self.titleLable.backgroundColor = [UIColor orangeColor];
self.titleLable.textColor = [UIColor blackColor];
self.titleLable.textAlignment = NSTextAlignmentCenter;
self.titleLable.frame = CGRectMake(0, self.frame.size.height / 2 - 25, self.frame.size.width, 50);
}
//重写set方法,用于给子控件设置数据
- (void)setDataModel:(DataModel *)dataModel
{
//给成员变量赋值
_dataModel = dataModel;
//给子控件赋值
_titleLable.text = dataModel.name;
}
------ 数据模型.h文件------
#import <Foundation/Foundation.h>
@interface DataModel : NSObject
//模型的数据
@property(strong, nonatomic) NSString * name;
@end
------ 数据模型.m文件------
#import "DataModel.h"
@implementation DataModel
@end
------ 调用自定控件.h文件------
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
------ 调用自定控件.m文件------
#import "ViewController.h"
#import "CustomView.h"
#import "DataModel.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"xib封装";
self.view.backgroundColor = [UIColor whiteColor];
[self addControls];
}
//添加控件方法
- (void)addControls
{
//创建数据模型
DataModel * dataModel = [[DataModel alloc] init];
dataModel.name = @"测试";
//生成自定义控件
CustomView * customView = [CustomView customView];
customView.frame = CGRectMake(0, 200, self.view.frame.size.width
, 100);
customView.dataModel =dataModel;
[self.view addSubview:customView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
3,在xib中使用另外一个xib封装
直接上代码
------ 调用自定控件.h文件------
#import <UIKit/UIKit.h>
@interface supView : UIView
@end
------ 调用自定控件.m文件------
#import "supView.h"
@interface supView()
//声明IBOutlet view的变量
@property (strong, nonatomic) IBOutlet UIView *view;
@end
@implementation supView
//重新,当走其他xib中创建class supView的UIview的时候会走这个方法
- (instancetype)initWithCoder:(NSCoder *)coder{
self = [super initWithCoder:coder];
if (self) {
[self setUI];
}
return self;
}
- (void)setUI{
//将xib与自身相绑定
[[NSBundle mainBundle] loadNibNamed:@"supView" owner:self options:nil];
[self addSubview:self.view];
self.frame = self.bounds;
}
@end
点击左侧的File's Owner,设置他的类(此处为ChildView),按住control从File's Owner往下拉到View松开,这是会出现Outlets,点击view进行一下关联。(往下拉要出现Outlets,需要先声明IBOutlet view的变量)
向testViewController.xib中添加UIView控件,该UIView的class属性设置为supView,及关联到自定义的试图,设置约束条件即可。