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,类名AppInfoView 2、创建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函数中,如何解决这个问题可以设置断点看图:
 
 
原文地址:https://www.cnblogs.com/-boy/p/4111681.html