首页 > 代码库 > UI基础xib的使用及xib的封装

UI基础xib的使用及xib的封装

一:

1、xib和stroryboard
Storyboard 描述软件界面,相对于xib比较重量级,一个stroryboard可以有多个场景。可以描述整个软件的所有界面xib 描述软件界面,一般用来描述一个界面中的某一个部分

本质就是代码创建的 

xib的加载过程,从xml中加载进来对界面的描述,并以此创建出来 JSAppView *view = [[JSAppView alloc] init];
View.frame = CGRectMake(0,0,85,90);

UIImageView *imageView = .......;[view addSubView:imageView];

...............

xib和storyboard的共同点都用来描述软件界面

都用Interface Builder工具来编辑都使用xml来存储 对界面的描述

xib和storyboard的区别,查看xib和storyboard的xml代码发现他们的区别仅仅是xib少了

Scenes和viewController

xib是轻量级的,用来描述局部的UI界面stroryboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系 

2:查看Xcode中storyBoard的xml展示文件

 

3 补充:、storyBoard或者xib中拖一个UIImageView 上不能拖其他控件到它上面

但是用代码的话,任何控件上都可以添加控件
按钮添加图片的两个特点
 1),background 中的图片会填充整个按钮
 2),image属性按照图片实际大小填充按钮
建议:小图片在按钮上设置用image属性
 
二:代码示例:
xib创建的view展示
 
// 通过xib创建view        UIView *subView = [[[NSBundle mainBundle] loadNibNamed:@"LLAppInfoView" owner:nil options:nil] lastObject];

 

三,xib的封装代码
xib封装的view
#import <UIKit/UIKit.h>@class LLAppInfo;@interface LLAppInfoView : UIView@property (nonatomic, strong) LLAppInfo *appInfo;+ (instancetype)appInfoView;@end
#import "LLAppInfoView.h"#import "LLAppInfo.h"@interface LLAppInfoView ()@property (weak, nonatomic) IBOutlet UIImageView *iconView;@property (weak, nonatomic) IBOutlet UIButton *downView;@property (weak, nonatomic) IBOutlet UILabel *nameView;- (IBAction)downBtnClick:(UIButton *)sender;@end@implementation LLAppInfoView+ (instancetype)appInfoView{    LLAppInfoView *subView = [[[NSBundle mainBundle] loadNibNamed:@"LLAppInfoView" owner:nil options:nil] lastObject];    return subView;}- (void)setAppInfo:(LLAppInfo *)appInfo{    _appInfo = appInfo;        self.iconView.image = [UIImage imageNamed:_appInfo.icon];    self.nameView.text = _appInfo.name;}- (IBAction)downBtnClick:(UIButton *)sender {        self.superview.userInteractionEnabled = NO;    sender.enabled = NO;            UILabel *textLab = [[UILabel alloc] init];        [self.superview addSubview:textLab];    textLab.text = [NSString stringWithFormat:@"%@ 正在下载", _appInfo.name];    textLab.backgroundColor = [UIColor grayColor];    textLab.alpha = 0;    textLab.textAlignment = NSTextAlignmentCenter;    CGFloat textLabW = 200;    CGFloat textLabH = 30;    CGFloat textLabX = (self.superview.frame.size.width -textLabW) * 0.5;    CGFloat textLabY = (self.superview.frame.size.height - textLabH) * 0.5;        textLab.frame = CGRectMake(textLabX, textLabY, textLabW, textLabH);    textLab.layer.cornerRadius = 10;    textLab.layer.masksToBounds = YES;    [UIView animateWithDuration:1.0 animations:^{        textLab.alpha = 0.9;                [UIView animateWithDuration:1 delay:5 options:UIViewAnimationOptionAllowUserInteraction animations:^{                        textLab.alpha = 0;        } completion:^(BOOL finished) {                        [textLab removeFromSuperview];            self.superview.userInteractionEnabled = YES;                    }];    }];}@end

数据模型 

#import <Foundation/Foundation.h>// 封装数据模型@interface LLAppInfo : NSObject/** 图片 */@property (nonatomic, copy) NSString *icon;/**名称 */@property (nonatomic, copy) NSString *name;#warning instancetype 和 id的区别+ (instancetype)appInfoWithDic:(NSDictionary *)dic;- (instancetype)initWithDic:(NSDictionary *)dic;+ (NSArray *)array;@end
#import "LLAppInfo.h"@implementation LLAppInfo- (instancetype)initWithDic:(NSDictionary *)dic{    if (self = [super init]) {        self.name = dic[@"name"];        self.icon = dic[@"icon"];    }    return self;}+ (instancetype)appInfoWithDic:(NSDictionary *)dic{    return [[self alloc] initWithDic:dic];}+ (NSArray *)array{    NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];        NSArray *dicArray = [NSArray arrayWithContentsOfFile:path];        NSMutableArray *appInfoM = [[NSMutableArray alloc] initWithCapacity:dicArray.count];        for (NSDictionary *dic in dicArray) {                [appInfoM addObject:[self appInfoWithDic:dic]];    }        return appInfoM;}@end

控制器

#import "ViewController.h"#import "LLAppInfo.h"#import "LLAppInfoView.h"@interface ViewController ()// 1,创建接受模型数据的数组@property (nonatomic, strong) NSArray *appInfos;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.        // 创建九宫格    [self createView];    }#pragma mark - 创建九宫格- (void)createView{    // 1,    // 1,1 列数    int colnumCount = 3;    CGFloat subViewWH= 100;    CGFloat marginX = (self.view.frame.size.width - 3*subViewWH) / (colnumCount + 1);    for (int i = 0; i<self.appInfos.count; i++) {                // 计算行、列        int row = i/colnumCount;        int col = i%colnumCount;                // 通过xib创建view//        UIView *subView = [[[NSBundle mainBundle] loadNibNamed:@"LLAppInfoView" owner:nil options:nil] lastObject];                // 通过xib封装的view创建view        LLAppInfoView *subView = [LLAppInfoView appInfoView];                [self.view addSubview:subView];                // 确定subView的frame        CGFloat subViewX = marginX + (marginX + subViewWH) * col;        CGFloat subViewY = 30 + (marginX + subViewWH) * row;        subView.frame = CGRectMake(subViewX, subViewY, subViewWH, subViewWH);#warning 将子控件添加到一个定义的view中的好处                LLAppInfo *appInfo = self.appInfos[i];        subView.appInfo = appInfo;        // 2,取子控件给子控件赋值(这里有两种方法)        /**            1,通过viewWithTag            2,通过subViews         */                // 这样写还是有问题,如果有多个控件tag标记太多,而且tag的性能很差        UIImageView *iconView = (UIImageView *)[subView viewWithTag:10];        iconView.image = [UIImage imageNamed:appInfo.icon];                UILabel *nameView =(UILabel *) [subView viewWithTag:20];        nameView.text = appInfo.name;                                    }}#pragma mark - 懒加载模型数据- (NSArray *)appInfos{    if (!_appInfos) {#warning NSBundle         //    NSLog(@"%@", NSHomeDirectory());        // 1,重plist中读取数据//        NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];//        NSArray *appInfo = [NSArray arrayWithContentsOfFile:path];//        //        //        _appInfos = appInfo;//        NSLog(@"%@", _appInfos);                        // 直接从封装好的代码中取数据        _appInfos = [LLAppInfo array];    }    return _appInfos;}@end

四:xib封装步骤

1)使用xib封装一个自定义view的步骤
1、新建一个继承UIView的自定义view,类名AppInfoView2、创建xib(xib的名字和自定义view的名字一样AppInfoView),来描述AppInfoView的内部结构3、修改xib中的UIView的类型改为AppInfoView
4、把xib中控件连线到AppInfoView
5、AppInfoView提供一个模型属性
6、重写模型的set方法,在set方法中给xib中对应的子控件赋值 

 

2)封装的好处

xib中完成的代码 controller得知道xib中具体的控件,产生依赖 为了减少依赖,把xib内部控件的赋值给封装起来

如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部的子控件的创建屏蔽起来,不让外界关心,这样不 管view内部怎么变化外界都不需要知道 

五:补充:
我们经常遇到程序报错直接跳到main函数中,如何解决这个问题可以设置断点看图:
 
 

UI基础xib的使用及xib的封装