天天看點

IOS開發UI基礎之綜合應用

一 懶加載

  • 作用:
    • 用到時再加載
    • 保證資料隻會被加載一次
  • 好處:
    • 節約記憶體空間
@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;
}
           

五 新增快速建立方法

  • 重寫initWithFrame
//   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原理

  • 1>根據custom class建立對象
  • 2>根據xib中的設定, 設定控件的相關屬性
shopView.backgroundColor = [UIColor redColor];
  shopView.frame = CGRectMake(, , , );
           
  • 3>建立所有子控件, 并且設定子控件的屬性
UIImageView *iv = [[UIImageView alloc] init];
  iv.frame = CGRectMake(, , , );
  UILabel *label = [[UILabel alloc] init];
  label.frame = CGRectMake(, , , );
           
  • 4>檢查子控件是否有連線, 如果有就進行關聯
self.iconView = iv;
    self.nameLabel = label;
           
  • 5>将所有子控件添加到父控件中
[shopView addSubview:iv];
     [shopView addSubview:label];