ios xib 四等分_ios Xib的几种用法[转]
大多數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的几种用法[转]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: webservice 暴漏接口_webS
- 下一篇: des vue 双倍长 解密_3DES双