懒加载 / plist文件 / 字典转模型 / 自定义View / layoutSubviews / Xib / 利用Xib自定义View / xib原理 / MVC /
/* 1. - 懒加载 (掌握) */ - 作用: + 用到时再加载 + 保证数据只会被加载一次 - 好处: + 节约内存空间 ```objc @interface ViewController () @property (nonatomic, strong)NSArray *shops; @end @implementation ViewController // 重写getter方法 - (NSArray *)shops { if (_shops == nil) { NSLog(@"创建一个新的数组"); _shops = @[ @{@"name":@"单肩包", @"icon":@"danjianbao"}, @{@"name":@"链条包", @"icon":@"liantiaobao"}, @{@"name":@"钱包", @"icon":@"qianbao"}, @{@"name":@"手提包", @"icon":@"shoutibao"} ]; } return _shops; } @end ``` --- /* 2. - plist文件 (掌握) */ -作用: + 将数据和逻辑分离 + 提高了代码的扩展性 - 获取plist文件的绝对路径 ```objc NSBundle *bundle = [NSBundle mainBundle]; NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"]; ``` - 注意点: + 文件名称中不能包含info单词 --- /* 3. - 字典转模型 */ - 字典的弊端 + 1.字典的key是一个字符串, 写错不会报错 + 2.英语不好, 单词记不住 + 3.由于key是一个字符串, 所以在编码的时候没有提示, 编码效率比较低 - 模型的优点 + 可以通过属性来获取值, 属性写错会报错 + 不用去记单词, 只需要记住以什么开头即可 + 由于属性有提示, 所以编码效率比较高 - 注意: + 字典转模型的操作应该封装到模型中 + 如果不封装在模型中的弊端: * 如果有很多地方都需要字典转模型, 那么很多地方都需要写重复的代码 * 需求变更所有字典转模型的地方都需要修改 ```objc + (instancetype)shopWithDict:(NSDictionary *)dict { NJShop *shop = [[self alloc] init]; shop.name = dict[@"name"]; shop.icon = dict[@"icon"]; return shop; } ``` - 规律: + 在开发中但凡看到字典,一般情况下都会创建一个与之对应的模型来保存字典中的数据 - 模型的类名命名注意: + 一般情况下在自定义一个类的时候会给每个类添加一个"类前缀", 这样可以避免多人开发发生冲突 // 4. - 自定义View - 目的: + 提高代码的复用性 + 屏蔽内部的实现细节 - 步骤: + 1.自定义一个类继承于UIView + 2.在initWithFrame方法中添加子控件 + 3.在layoutSubviews中设置子控件的位置 + 4.提供一个属性保存外界传入的数据(模型对象), 重写setter方法设置子控件的数据 - 类工厂方法(便利构造器) + 按照苹果的风格和规范, 一般情况一个用于创建对象的对象方法会对应一个类方法 + 可以通过类工厂方法, 快速的根据数据创建一个对象 - 注意点: + 返回值一定要使用instancetype, 不要使用id + 在类工厂方法中创建对象, 使用self, 不要使用类名 --- /* 5.- layoutSubviews */ - 作用: + 布局子控件, 用于调整子控件的位置 - 什么时候调用 + 控件第一次被创建 + 控件的尺寸(size)被修改会调用 - 注意点: + 重写layoutSubviews方法, 一定要调用父类的方法 --- /* 6. - Xib */ - 什么是Xib + Xib和Storyboard一样都是用来描述界面的 + Xib是Storyboard的前身 - Xib和storyboard对比 - 共同点: + 都用来描述软件界面 + 都用Interface Builder工具来编辑 + 本质都是转换成代码去创建控件 - 不同点 + Xib是轻量级的,用来描述局部的UI界面 + Storyboard是重量级的,用来描述整个软件的多个界面,并且能展示多个界面之间的跳转关系 - 如何加载xib - 第一种方式 ```objc NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib文件名" owner:nil options:nil] ``` - 第二种方式 ```objc UINib *nib = [UINib nibWithNibName:@"xib文件名" bundle:nil]; NSArray *views = [nib instantiateWithOwner:nil options:nil]; ``` - 规律 + 一般情况下苹果的方法中要求传入一个bundle参数, 直接传nil就代表mainBundle --- /* 7. - 利用Xib自定义View */ - 步骤 + 1.新建一个Xib描述界面 + 2.新建一个继承于Xib界面中父控件类型的类来管理界面 + 3.在xib中关联界面和类 + 4.重写awakeFromNib方法, 进行一些初始化 + 5.提供一个属性保存外界传入的数据(模型对象), 重写setter方法设置子控件的数据 - 注意点: - 不应该在控制器中加载xib, 应该将加载xib的操作封装到自定义view中 ```objc + (instancetype)shopView { return [[[NSBundle mainBundle] loadNibNamed:@"XMGShopView" owner:nil options:nil] firstObject]; } ``` - 方法的执行顺序 + 如果是通过xib或者Storyboard创建一个控件, 不会调用initWithFrame方法 + 在"创建时"会调用initWithCoder方法 * 控件不一定被创建好了 + 在"创建后"会调用awakeFromNib * 控件一定被创建好了 --- /* 8. - xib原理 */ + 1. 根据custom class创建对象 ``` XMGShopView *shopView = [XMGShopView alloc] init]; ``` + 2. 根据xib中的设置, 设置控件的相关属性 ``` shopView.backgroundColor = [UIColor redColor]; shopView.frame = CGRectMake(0, 0, 70, 100); ``` + 3. 创建所有子控件, 并且设置子控件的属性 ``` UIImageView *iv = [[UIImageView alloc] init]; iv.frame = CGRectMake(0, 0, 70, 70); UILabel *label = [[UILabel alloc] init]; label.frame = CGRectMake(0, 70, 70, 30); ``` + 4. 检查子控件是否有连线, 如果有就进行关联 ``` self.iconView = iv; self.nameLabel = label; ``` + 5.将所有子控件添加到父控件中 ``` [shopView addSubview:iv]; [shopView addSubview:label]; ``` /* 9. - MVC */ + M --> Model --> 专门用于保存数据 + V --> View --> 专门用户展示数据 + C --> Controller -->专门用于编写逻辑代码(赋值管理M和V) - 总统管理国家的例子 + 如果一个人管理, 那么就累死了 + 分级管理, 各司其职