大多数Ios开发者都喜欢运用xib以及约束来布局,这样省去了大量初始化代码,但是xib的使用也是存在不少差异的:

一.xib的几个重要属性

xib的文件名

File's owner

xib中的视图class

xib文件中的视图Outlet指向

二.Demo实现

1.加载xib中File's owner为nil的视图

blueView.png

ViewController:

- (void)addBlueView {

// BlueView.xib的File's Owner为nil

NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"BlueView" owner:nil options:nil];

self.blueView = views[0];

// 从xib加载进来的View大小是确定的,但是该视图在父视图中的位置是不确定的

// 此外,视图中的子视图也是原封不动地Load进来的

CGRect rect = _blueView.frame;

rect.origin.x += 37.5f;

rect.origin.y += 80.0f;

_blueView.frame = rect;

[self.view addSubview:_blueView];

}

运行结果:

blueViewResult.png

总结:

File’s Owner为nil的xib文件中的视图属于通用视图,在工程中可以复用

从xib加载进来的View大小是确定的,但是该视图在父视图中的位置是不确定的,因此需要开发者自行指定

视图中的所有子视图会被原封不动地Load进来

2.加载File's owner为self的视图

greenView.png

ViewController

- (void)addGreenView {

// GreenView.xib的File's Owner设为self,并建立了一个从该xib的View到self的IBOutlet greenView

[[NSBundle mainBundle] loadNibNamed:@"GreenView" owner:self options:nil];

// 只要self主动调用Load XIB的方法,self持有的IBOutlet指向的视图就会被初始化

// 这里不需要通过views[0]的方式存取视图

CGRect rect = _greenView.frame;

rect.origin.x = _blueView.frame.origin.x;

rect.origin.y = _blueView.frame.origin.y + 80.0f;

_greenView.frame = rect;

[self.view addSubview:_greenView];

}

运行结果:

greenViewResult.png

总结:

File’s Owner不为nil的xib文件中的视图属于专用视图,在工程中不应该被复用

只要self主动调用loadNibNamed:owner:options:方法,self持有的IBOutlet指向的视图就会被初始化

存取xib中的视图不用views[0]的方式,而是通过IBOutlet类型的property进行存取

3.加载xib中File’s Owner为特定类的视图

redView.png

RedViewOwner:

@interface RedViewOwner : NSObject

@property (strong, nonatomic) IBOutlet UIView *redView;

@end

ViewController:

- (void)addRedView {

self.redViewOwner = [RedViewOwner new];

[[NSBundle mainBundle] loadNibNamed:@"RedView" owner:self.redViewOwner options:nil];

UIView *redView = _redViewOwner.redView;

CGRect rect = redView.frame;

rect.origin.x = _greenView.frame.origin.x;

rect.origin.y = CGRectGetMaxY(_greenView.frame) + 30;

redView.frame = rect;

[self.view addSubview:redView];

}

结果:

redresult.png

总结:

File’s Owner类可以封装视图中的各种逻辑,而不仅仅是提供视图内容

只要通过File’s Owner类主动调用loadNibNamed:owner:options:方法,该IBOutlet指向的视图就会被初始化

4.加载xib中文件名和视图类名一致的视图(File’s Owner为nil)

yellowview.png

@implementation YellowView

+ (instancetype)loadYellowViewFromXib {

// 加载xib中的视图,其中xib文件名和本类类名必须一致

// 这个xib文件的File's Owner必须为空

// 这个xib文件必须只拥有一个视图,并且该视图的class为本类

NSArray *views = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];

return views[0];

}

@end

ViewController:

- (void)addYellowView {

self.yellowView = [YellowView loadYellowViewFromXib];

CGRect rect = _yellowView.frame;

rect.origin.x = _redViewOwner.redView.frame.origin.x;

rect.origin.y = CGRectGetMaxY(_redViewOwner.redView.frame) + 30;

_yellowView.frame = rect;

[self.view addSubview:self.yellowView];

}

结果:

yellowresult.png

总结:

这里的viewFromNib方法只是对loadNibNamed:owner:options:方法的一个简单封装,要求的条件包括: - xib文件名和本类类名必须一致 - 这个xib文件的File’s Owner必须为空 - 这个xib文件必须只拥有一个视图,并且该视图的class为本类

5. 通过UIViewController的initWithNibName:bundle:方法加载xib文件中的视图

blackView.png

如果想要self.view是视图中的底层view,那么要连线File's owner 和view

blackviewll.png

BlackViewController

@interface BlackViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *label;

+ (instancetype)viewControllerFromNIB;

@end

+ (instancetype)viewControllerFromNIB {

return [[BlackViewController alloc] initWithNibName:NSStringFromClass([self class]) bundle:[NSBundle mainBundle]];

}

ViewController

- (void)addBlackView {

self.blackVC = [[BlackViewController alloc] initWithNibName:@"BlackView" bundle:[NSBundle mainBundle]];

UIView *views = self.blackVC.view;

CGRect rect = views.frame;

rect.origin.x = _yellowView.frame.origin.x;

rect.origin.y = CGRectGetMaxY(_yellowView.frame) + 20;

views.frame = rect;

[self.view addSubview:views];

}

总结:

将xib的File’s Owner设成一个UIViewController子类,可以将这个xib文件的视图展示和外部响应事件(例如点击一个按钮触发的点击事件,该视图的手势事件等)全部封装在一个View Controller中,如果把按钮的点击事件封装在一个UIView类中,貌似破坏了MVC模式,因此最好将xib的File’s Owner设成一个UIViewController子类,该类可以通过addChildViewController方法将其添加到现有的View Controller上。如果只是希望加载视图,可以通过viewcontroller.view存取。

6. 通过UIViewController+NIB加载xib文件中的View Controller类和其视图

GrayView.xib

grayView.png

grayviewaction.png

UIViewController+NIB.h/m

@interface UIViewController (NIB)

// 要求xib文件名和View Controller类名一致

+ (instancetype)loadFromNib;

@end

@implementation UIViewController (NIB)

+ (instancetype)loadFromNib {

// [self class]会由调用的类决定

Class controllerClass = [self class];

NSLog(@"class = %@", controllerClass);

return [[controllerClass alloc] initWithNibName:NSStringFromClass(controllerClass) bundle:[NSBundle mainBundle]];

}

@end

GrayViewController.h/m

@interface GrayViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *titleLabel;

@property (weak, nonatomic) IBOutlet UIButton *actionButton;

@end

@implementation GrayViewController

- (void)viewDidLoad {

[super viewDidLoad];

self.view.backgroundColor = [UIColor grayColor];

self.titleLabel.text = @"Gray View";

self.titleLabel.textColor = [UIColor whiteColor];

self.titleLabel.textAlignment = NSTextAlignmentCenter;

self.titleLabel.font = [UIFont systemFontOfSize:8.5f];

[self.actionButton setTitle:@"action" forState:UIControlStateNormal];

[self.actionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

// 推荐从XIB文件中加载View Controller的方法,这种方法可以将XIB文件中的视图和其按钮响应事件全部封装在GrayViewController

// 如果GrayViewController的按钮响应事件由MainViewController作出响应,那么二者的耦合度就过高

// 建议:

// 单纯的通用View展示,使用从xib文件加载视图的方法,File's Owner设为nil

// 特定拥有者的View展示,从xib文件加载视图时,File's Owner设为拥有者

// 如果视图中有按钮响应事件,或其它可以和用户交互的事件,建议采用从XIB文件中加载View Controller的方法,这样可以封装UI展示和交互事件

- (IBAction)action:(id)sender {

NSLog(@"action");

}

@end

ViewController

...

@property (strong, nonatomic) GrayViewController *grayViewController;

...

- (void)loadGrayViewFromXIB {

self.grayViewController = [GrayViewController loadFromNib];

UIView *grayView = _grayViewController.view;

UIView *blackView = _blackViewController.view;

CGRect rect = grayView.frame;

rect.origin.x = blackView.frame.origin.x;

rect.origin.y = blackView.frame.origin.y + 80.0f;

grayView.frame = rect;

[self.view addSubview:grayView];

}

结果:

grayViewResult.png

总结:

这里我专门写了一个UIViewController+NIB的category,只需要调用loadFromNib类方法就可以加载xib中的视图。要求: - xib文件的File’s Owner必须设置为对应的View Controller类

三.总结

在写界面时同时混用xib和代码可以提高效率,而对xib的使用主要体现在其专用性和通用性上。

对于一些专门的界面,例如App中的设置界面,纯代码写难免会浪费时间,此时可以通过xib文件的拖控件方法来定制。这个xib是专用于某一个界面的,目的是提高效率

对于一些通用的控件甚至界面,例如一个很漂亮但实现起来非常复杂的按钮,此时可以通过load xib文件中的视图来快速添加。这个xib对于所有视图是共用的,目的是提高可复用性。

对于通用的xib:

如果xib只是单纯的界面展示,那么File’s Owner可以随意。

如果xib中包含了按钮、手势等用户输入事件,那么File’s Owner最好设置为UIViewController类的子类。

四.发现的问题

以前使用xib时一直都有点疑问,xib中可以有多个视图控件,但是从xib中load出来的是一个数组,那么怎么确定哪个对象对应的是哪个控件呢?

TestView.xib

testView.png

ViewController:

- (void)loadFromNib {

NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"TestView" owner:nil options:nil];

[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

NSLog(@"%ld----%@",idx,NSStringFromClass([obj class]));

}];

}

控制台输出如下:

2017-03-30 17:53:21.128 启动页[7655:288700] 0----UIView

2017-03-30 17:53:21.128 启动页[7655:288700] 1----UIButton

2017-03-30 17:53:21.128 启动页[7655:288700] 2----UITableView

2017-03-30 17:53:21.128 启动页[7655:288700] 3----UIImageView

结论:

从xib中load出来的views数组中视图对象的排列顺序和xib scene中的对象排列顺序一致(其实就是xml文件中元素的排序而已)。

result.png

ios xib 四等分_ios Xib的几种用法[转]相关推荐

  1. ios xib 四等分_iOS XIB总结(一)

    一.XIB文件使用简介 1.添加约束 Horizontally in Container(与容器平行)   Align Center X to superview,   " |" ...

  2. ios xib 四等分_iOS界面布局的核心以及TangramKit介绍

    前言 layoutSubviews方法来完成界面布局,只不过在一些语法和属性设置上略有一些差异.可以这么说TangramKit是MyLayout布局库的一个升级版本.大家可以通过访问下面的github ...

  3. ios wifi 定位_iOS 中的三种定位方式

    1.手机基站定位 原理: 每个手机基站都有一个标识符,iPhone或3G iPad可以搜集周围所有收到信号的基站和它们的标识符,通过联网发送到苹果云端服务器,再由服务器根据这些基站的的位置信息查询并计 ...

  4. **IOS:xib文件解析(xib和storyboard的比较,一个轻量级一个重量级)

    使用Xcode做iOS项目,经常会和Xib文件打交道,因为Xib文件直观的展现出运行时视图的外观,所以上手非常容易,使用也很方便,但对于从未用纯代码写过视图的童鞋,多数对Xib的理解有些片面. Xib ...

  5. 李洪强iOS开发之后使用XIB实现横向滚动的UIScrollView

    李洪强iOS开发之后使用XIB实现横向滚动的UIScrollView 11111222

  6. iOS开发UI篇—xib的简单使用

    一.简单介绍 xib和storyboard的比较,一个轻量级一个重量级. 共同点: 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: Xib是轻量级的,用来描述局部的UI ...

  7. IOS学习之UISwitch控件两种使用方法和监听

    IOS学习之UISwitch控件两种使用方法和监听 分类: IOS开发入门2012-06-15 11:48 1363人阅读 评论(0) 收藏 举报 一.第一种创建UISwitch控件的方法,在代码中动 ...

  8. iOS: JS和Native交互的两种方法,iosjsnative交互

    iOS: JS和Native交互的两种方法,iosjsnative交互 背景: UIWebView: iOS 用来展示 web 端内容的控件. 1. 核心方法: - (NSString*)string ...

  9. ios触摸超出_iOS触摸事件处理

    在开发过程中,大家或多或少的都会碰到令人头疼的手势冲突问题,正好前两天碰到一个类似的bug,于是借着这个机会了解了iOS中的事件传递与处理的相关内容,整理出来方便以后查阅. iPhone的成功,很大的 ...

最新文章

  1. 淘金尖端领域:全球量子技术最新投资趋势
  2. 深入剖析Android系统
  3. hadoop中汉字与英文字符混合的keyword做为combine的key的问题
  4. 自由自在公司意式手工冰淇淋以“怪“取胜
  5. 不存在从node到node*的适当转换函数_C++构造函数和初始化表
  6. SAP Spartacus Ngrx 使用的一些准则
  7. 【WEB API项目实战干货系列】- API访问客户端(WebApiClient适用于MVC/WebForms/WinForm)(四)
  8. D - ABC Conjecture Gym - 102798D
  9. vb添加GIF动态图片
  10. AttributeError: 'dict' object has no attribute 'has_key'
  11. acrobat xi pro 简体中文语言支持包_出图利器佳能PRO-541S绘图仪现货报价-佳能 PRO-541S_西安大幅面打印机行情...
  12. 2018.11.22 mac中允许所有安装来源的命令 Mac窗口标题显示文件的路径
  13. MRD市场需求文档结构
  14. 软考信息安全工程师经验分享以及报考建议
  15. 蓝桥杯矩阵求和_刷蓝桥杯官网习题,准备蓝桥杯的小伙伴,一起来交流吧(✪ω✪)。(2月27日更新)...
  16. 僵尸进程和孤儿进程-(转自Anker's Blog)
  17. Ubuntu安装intel集显驱动
  18. 【讲座笔记】如何让你的皮肤变年轻?
  19. 下载钉钉直播回放视频
  20. 揭秘交换机市场内幕,“准工业级”猫腻你中招了吗?

热门文章

  1. Android Studio添加代码头注释使用
  2. centeos7安装mariadb
  3. 打字游戏--飞机大战
  4. Django缓存机制
  5. 2022-2028年中国三网融合产业深度调研及投资前景预测报告
  6. PyTorch 笔记(15)— 分别使用 tensor、autograd、torch.nn 搭建简易神经网络
  7. JS中的call()方法和apply()方法用法总结
  8. Keil中使用宏编译来定义DEBUG输出
  9. [建议] GCC 新手入门【转】
  10. 将moss 2007的模板文件导入到moss 2010