自定义封装视图的两种方式纯代码和xib的区别

2018-05-30  本文已影响0人  十一月的加州一号公路

在开发的过程中,我们可能会碰到这样的情况,一个试图的内部的控件比较多,并且这个试图在多次出现,那我们就要考虑对其进行相应的封装,报漏外部数据模型,这样我们只需要在请求完毕数据,将数据赋值给相应模型,试图拿到数据对其内部的子控件数据进行赋值。

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


1527678533180.jpg

自定义View的类并与类的属性连线


1527677918785.jpg
1527678014050.jpg
设置自定义View为可变的尺寸,View的背景色
1527678245988.jpg

关闭自动布局(Autolayout),才可以在layoutSubviews里重新设置Button的Frame值


1527678352395.jpg

------ 自定控件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的变量)

1527680742491.jpg

向testViewController.xib中添加UIView控件,该UIView的class属性设置为supView,及关联到自定义的试图,设置约束条件即可。

1527681338854.jpg
上一篇下一篇

猜你喜欢

热点阅读