iOS 指定初始化方法

級別: ★☆☆☆☆
標籤:「NS_DESIGNATED_INITIALIZER 」「NS_UNAVAILABLE」「iOS指定初始化方法」
做者: WYW
審校: QiShare團隊php


前言:筆者最近了解了部分SDK開發相關的內容,在涉及指定視圖控制器(下文用VC代指視圖控制器)的初始化方法的時候,遇到了一些問題。這裏筆者給你們分享下設置方法,若有不一樣看法,敬請指教。git

筆者遇到的問題以下:github

筆者但願 使用SDK的業務可以使用 SDK中肯定的初始化VC的方法; 下邊筆者以須要傳入VC的導航欄標題並初始化相應VC爲例,來闡明相關問題。 對於上述狀況,有多種處理方式,如:算法

  1. 在SDK暴露的頭文件中,文字說明,用哪一個初始化方法;在文檔中說明, 用哪一個初始化方法;在提供的Demo中,寫明相應地示例代碼。
  2. 利用系統給的宏NS_DESIGNATED_INITIALIZER指定vc初始化方法 指定初始化方法部分,可使用宏NS_DESIGNATED_INITIALIZER指定,那麼若是業務沒有看SDK頭文件,直接使用new 或者 alloc init的方式指定初始化方法,那麼咱們初始化VC所需的導航欄標題就不能得以正常傳入。

對於這種狀況,咱們能夠提供以下3種方法:bash

  1. 把不想業務使用的初始化方法,使用系統宏 NS_UNAVAILABLE 把相應初始化方法設置爲不可用;如禁用new ,這樣的效果是:業務若是想使用new 初始化VC,會發現有錯誤提示,使用這種方法比較簡單。
  1. 對於不想業務使用的初始化方法,在實現文件中,實現相應的方法,而且給予默認值。好比說對於初始化VC的導航欄標題的狀況,給定默認標題爲defaultNavigationTitle。不過這種初始化方法,不適用傳入重要參數的狀況,否則業務會以爲怪怪的。另外這種方式,之後若是有相關改動,可能改動代碼會較多。
  1. 對於不想業務使用的初始化方法,在實現文件中,實現相應的方法,而且拋出崩潰,而且指定崩潰緣由,在崩潰緣由中說明應該使用的初始化VC的方法。對於這種方式,若是之後有改動,可能改動代碼會較多。 相好比上三種處理方式,筆者更傾向於使用第一種,若是你有其餘看法,歡迎討論。

下邊咱們仍以初始化VC時,指定傳入導航欄標題爲例,貼上相關的示例代碼。微信

第一種方式:ide

// .h 文件

- (instancetype)initWithSomething:(id)someThing NS_DESIGNATED_INITIALIZER;

- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
複製代碼
// .m 文件

/*! @brief 導航欄title */
@property (nonatomic, copy) NSString *navTitle;


- (instancetype)initWithSomething:(id)someThing {
    // Cannot assign to 'self' outside of a method in the init family
    // 指定初始化方法須要以 1. init開頭 2. 而且init後邊緊挨着地字母是大寫的
    self = [super initWithNibName:nil bundle:nil];
    if (!self) {
        return nil;
    }
    _navTitle = someThing;
    [self commonInit];
    return self;
}

- (void)commonInit {
    
    self.navigationItem.title = _navTitle;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
}
複製代碼

第二種方式:oop

.h
- (instancetype)initWithSomething:(id)someThing;

複製代碼
// .m 文件

/*! @brief 導航欄title */
@property (nonatomic, copy) NSString *navTitle;


- (instancetype)initWithSomething:(id)someThing {
    
    self = [super init];
    if (!self) {
        return nil;
    }
    _navTitle = someThing;
    return self;
}

- (instancetype)init {
    
    self = [super init];
    if (!self) {
        return nil;
    }
    [self commonInit];
    return self;
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (!self) {
        return nil;
    }
    [self commonInit];
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    
    self = [super initWithCoder:aDecoder];
    if (!self) {
        return nil;
    }
    [self commonInit];
    return self;
}

- (void)commonInit {
    
    _navTitle = @"Default";
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = _navTitle;
    self.view.backgroundColor = [UIColor whiteColor];
}

複製代碼

第三種方式:學習

// .h 文件
- (instancetype)initWithSomething:(id)someThing;

複製代碼
// .m 文件
static NSString *const kExceptionName = @"初始化方法有誤";
static NSString *const kExceptionReason = @"請使用initWithSomething:進行初始化";

/*! @brief 導航欄title */
@property (nonatomic, copy) NSString *navTitle;


- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = _navTitle;
    self.view.backgroundColor = [UIColor whiteColor];
}

+ (instancetype)new {
    
    @throw [[self class] initExceptioin];
    return nil;
}

- (instancetype)init {
    
    @throw [[self class] initExceptioin];
    return nil;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    
    @throw [[self class] initExceptioin];
    return nil;
}

- (instancetype)initWithSomething:(id)someThing {
    
    self = [super init];
    if (!self) {
        return nil;
    }
    _navTitle = someThing;
    
    return self;
}

+ (NSException *)initExceptioin {
    
    return [NSException exceptionWithName:kExceptionName reason:kExceptionReason userInfo:nil];
}

複製代碼

Demo:

Demo:QiDesignatedInitializerui

參考學習網址


小編微信:可加並拉入《QiShare技術交流羣》。

關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)

推薦文章:
UIView中的hitTest方法
iOS關於tabBar的幾處筆記
A的女兒是B的女兒的媽媽,A是B的誰?
算法小專欄:選擇排序
iOS Runloop(一)
iOS 經常使用調試方法:LLDB命令
iOS 經常使用調試方法:斷點
iOS 經常使用調試方法:靜態分析
奇舞週刊

相關文章
相關標籤/搜索