iOS 指定初始化方法

QiShare發表於2019-05-13

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


前言:筆者最近了解了部分SDK開發相關的內容,在涉及指定檢視控制器(下文用VC代指檢視控制器)的初始化方法的時候,遇到了一些問題。這裡筆者給大家分享下設定方法,如有不同見解,敬請指教。

筆者遇到的問題如下:

筆者希望 使用SDK的業務能夠使用 SDK中確定的初始化VC的方法; 下邊筆者以需要傳入VC的導航欄標題並初始化相應VC為例,來闡明相關問題。 對於上述情況,有多種處理方式,如:

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

對於這種情況,我們可以提供如下3種方法:

  1. 把不想業務使用的初始化方法,使用系統巨集 NS_UNAVAILABLE 把相應初始化方法設定為不可用;如禁用new ,這樣的效果是:業務如果想使用new 初始化VC,會發現有錯誤提示,使用這種方法比較簡單。
  1. 對於不想業務使用的初始化方法,在實現檔案中,實現相應的方法,並且給予預設值。比如說對於初始化VC的導航欄標題的情況,給定預設標題為defaultNavigationTitle。不過這種初始化方法,不適用傳入重要引數的情況,不然業務會覺得怪怪的。另外這種方式,以後如果有相關改動,可能改動程式碼會較多。
  1. 對於不想業務使用的初始化方法,在實現檔案中,實現相應的方法,並且丟擲崩潰,並且指定崩潰原因,在崩潰原因中說明應該使用的初始化VC的方法。對於這種方式,如果以後有改動,可能改動程式碼會較多。 相比如上三種處理方式,筆者更傾向於使用第一種,如果你有其他見解,歡迎討論。

下邊我們仍以初始化VC時,指定傳入導航欄標題為例,貼上相關的示例程式碼。

第一種方式:

// .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];
}
複製程式碼

第二種方式:

.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:QiDesignatedInitializer

參考學習網址


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

iOS 指定初始化方法

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

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

相關文章