美文网首页
自定义封装视图的两种方式纯代码和xib的区别

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

作者: 十一月的加州一号公路 | 来源:发表于2018-05-30 19:19 被阅读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

    相关文章

      网友评论

          本文标题:自定义封装视图的两种方式纯代码和xib的区别

          本文链接:https://www.haomeiwen.com/subject/ieutsftx.html