一 懶加載
@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
二 plist檔案
- plist檔案作用:
- 擷取plist檔案的絕對路徑
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"];
// 根據路徑加載plist檔案
_shop = [NSArray arrayWithContentOfFile:path];
注意點: 檔案名稱中不能包含info單詞
三 字典轉模型
- 字典的弊端
- 1.字典的key是一個字元串, 寫錯不會報錯
- 2.英語不好, 單詞記不住
- 3.由于key是一個字元串, 是以在編碼的時候沒有提示, 編碼效率比較低
- 模型的優點
- 可以通過屬性來擷取值, 屬性寫錯會報錯
- 不用去記單詞, 隻需要記住以什麼開頭即可
- 由于屬性有提示, 是以編碼效率比較高
- 注意:
- 字典轉模型的操作應該封裝到模型中
- 如果不封裝在模型中的弊端:
- 如果有很多地方都需要字典轉模型, 那麼很多地方都需要寫重複的代碼
- 需求變更所有字典轉模型的地方都需要修改
+ (instancetype)shopWithDict:(NSDictionary *)dict
{
NJShop *shop = [[self alloc] init];
shop.name = dict[@"name"];
shop.icon = dict[@"icon"];
return shop;
}
- 規律:
- 在開發中但凡看到字典,一般情況下都會建立一個與之對應的模型來儲存字典中的資料
- 模型的類名命名注意:
- 一般情況下在自定義一個類的時候會給每個類添加一個”類字首”, 這樣可以避免多人開發發生沖突
四 自定義view
- 自定義View
- 目的:
- 步驟:
- 1.自定義一個類繼承于UIView
- 2.在initWithFrame方法中添加子控件
- 3.在layoutSubviews中設定子控件的位置
- 4.提供一個屬性儲存外界傳入的資料(模型對象), 重寫setter方法設定子控件的資料
- 類工廠方法(便利構造器)
- 按照蘋果的風格和規範, 一般情況一個用于建立對象的對象方法會對應一個類方法
- 可以通過類工廠方法, 快速的根據資料建立一個對象
- 注意點:
- 傳回值一定要使用instancetype, 不要使用id
- 在類工廠方法中建立對象, 使用self, 不要使用類名
- layoutSubviews
- 作用:
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat shopViewWidth = self.frame.size.width;
CGFloat shopViewHeight = self.frame.size.height;
// 布局圖檔的位置
self.iv.frame = CGRectMake(, , shopViewWidth, shopViewWidth);
// 布局文本的位置
self.lable.frame = CGRectMake(, shopViewWidth, shopViewWidth, shopViewHeight - self.iv.frame.size.height);
}
- 什麼時候調用
- 控件第一次被建立
- 控件的尺寸(size)被修改會調用
- 修改位置不會調用
- 注意點:
- 重寫layoutSubviews方法, 一定要調用父類的方法([super layoutSubviews])
- 重寫set方法,設定子控件資料
- (void)setShop:(NJShop *)shop
{
_shop = shop;
// 設定子控件的資料
self.iv.image = [UIImage imageNamed:_shop.icon];
self.lable.text = _shop.name;
}
五 新增快速建立方法
// init方法内部會調用initWithFrame
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
// 1.建立一張圖檔
UIImageView *iv = [[UIImageView alloc] init];
iv.backgroundColor = [UIColor yellowColor];
[self addSubview:iv];
self.iv = iv;
// 2.建立一個文本
UILabel *lable = [[UILabel alloc] init];
lable.backgroundColor = [UIColor purpleColor];
lable.textAlignment = NSTextAlignmentCenter;
[self addSubview:lable];
self.lable = lable;
}
return self;
}
注意: 一般情況下自定義一個控件會重寫控件的initWithFrame方法, , 因為使用者可能通過init方法建立也可能通過initWithFrame方法建立, 為了保證無論使用者通過哪一個方法建立都能添加子控件, 是以重寫initWithFrame
NJShopView *shopView = [NJShopView shopViewWithShop: self.shops[index]];
// NJShopView *shopView = [[NJShopView alloc] initWithShop:self.shops[index]];
shopView.backgroundColor = [UIColor redColor];
shopView.frame = CGRectMake(shopX, shopY, , );
[self.shopsView addSubview:shopView];
// 注意:自定義構造方法中的With的W一定要大寫
- (instancetype)initWithShop:(NJShop *)shop;
+ (instancetype)shopViewWithShop:(NJShop *)shop;
- (instancetype)initWithShop:(NJShop *)shop
{
if (self = [super init]) {
self.shop = shop;
}
return self;
}
+ (instancetype)shopViewWithShop:(NJShop *)shop
{
// 注意: 如果在類方法中建立對象, 建議使用self, 不要使用類名
return [[self alloc] initWithShop:shop];
}
六 Xib
- 什麼是Xib
- Xib和Storyboard一樣都是用來描述界面的
- Xib是Storyboard的前身
- Xib和storyboard對比
- 共同點:
- 都用來描述軟體界面
- 都用Interface Builder工具來編輯
- 本質都是轉換成代碼去建立控件
- 不同點
- Xib是輕量級的,用來描述局部的UI界面
- Storyboard是重量級的,用來描述整個軟體的多個界面,并且能展示多個界面之間的跳轉關系
- 如何加載xib
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib檔案名" owner:nil options:nil]
// 注意: 建立UINib對象時需要傳入一個bundle, 如果是去mainBundle中查找, 那麼可以直接傳一個nil
UINib *nib = [UINib nibWithNibName:@"xib檔案名" bundle:nil];
NSArray *views = [nib instantiateWithOwner:nil options:nil];
- 規律
- 一般情況下蘋果的方法中要求傳入一個bundle參數, 直接傳nil就代表mainBundle
七 通過Xib自定義View
- 步驟
- 1.建立一個Xib描述界面
- 2.建立一個繼承于Xib界面中父控件類型的類來管理界面
- 3.在xib中關聯界面和類
- 4.重寫awakeFromNib方法, 進行一些初始化
- 5.提供一個屬性儲存外界傳入的資料(模型對象), 重寫setter方法設定子控件的資料
- 代碼示例:
// 加載XIB
XMGShopView *shopView = [[[NSBundle mainBundle] loadNibNamed:@"XMGShopView" owner:nil options:nil] firstObject];
// 設定frame
CGRect tempFrame = shopView.frame;
tempFrame.origin.x = shopX;
tempFrame.origin.y = shopY;
shopView.frame = tempFrame;
// 設定資料
NJShop *shop = self.shops[index];
shopView.iconView.image = [UIImage imageNamed:shop.icon];
shopView.nameLabel.text = shop.name;
// 添加子控件
[self.shopsView addSubview:shopView];
- 注意點:不應該在控制器中加載xib, 應該将加載xib的操作封裝到自定義view中
+ (instancetype)shopView
{
return [[[NSBundle mainBundle] loadNibNamed:@"XMGShopView" owner:nil options:nil] firstObject];
}
- 方法的執行順序
- 如果是通過xib或者Storyboard建立一個控件, 不會調用initWithFrame方法
- 在”建立時”會調用initWithCoder方法
- 在”建立後”會調用awakeFromNib
八 Xib原理
shopView.backgroundColor = [UIColor redColor];
shopView.frame = CGRectMake(, , , );
UIImageView *iv = [[UIImageView alloc] init];
iv.frame = CGRectMake(, , , );
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(, , , );
self.iconView = iv;
self.nameLabel = label;
[shopView addSubview:iv];
[shopView addSubview:label];