Nullarihyon 1.7
Xcode8にNullability Violationをチェックする機能が入ると聞いて一晩泣き明かしましたが、それはそれとしてちまちま開発を続けています。Xcode8との比較はまたそのうち。
Nullarihyon 1.6では「nonnullなインスタンス変数に代入があるかどうかを確認する機能」を実装しています。
NS_ASSUME_NONNULL_BEGIN @interface Person : NSObject @property (nonatomic) NSString *name; @property (nonatomic) NSString *address; - (instancetype)initWithName:(NSString *)name address:(NSString *)address; @end @implementation Person - (instancetype)initWithName:(NSString *)name address:(NSString *)address { self = [self init]; self.name = name; // addressを設定するのを忘れている return self; } @end NS_ASSUME_NONNULL_END
こういうプログラムがあったときに、警告を出すようになっています。init
的なメソッド全てで検査すればいい気もしますが、ひとまずはオプトインで __attribute__((annotate("nlh_initializer")))
がついたものだけ検査します。
- (instancetype)initWithName:(NSString *)name address:(NSString *)address __attribute__((annotate("nlh_initializer")));
などとつけましょう。
この属性がついたメソッドでは、
- 全てのnonnullなインスタンス変数に何かを代入する
- 別の
__attribute__((annotate("nlh_initializer")))
なメソッドを呼ぶ
のどちらかの条件が成り立っていないといけません。そうでない場合は、nonnullなインスタンス変数が初期化されずに残っているとみなして、警告を出します。
この機能で、Nullarihyonで検査してokなプログラムは(キャストによって確信犯的に導入されたもの除けば)nonnullなメソッド・プロパティがnil
を返すことはないことが保証できるようになったはずです。nonnullをつけたい場合には、
- Nullarihyonをインストール、セットアップする
- 型にnonnullをつけて回る
init
にattributeをつける- コンパイルして、警告をちまちま直す
とすれば、かなり安全に作業が進められます。逆に言うと、この「init
でnonnullなインスタンス変数が初期化されずに残る問題」はかなり厄介で危険なので、Nullarihyonを使わないのであれば気軽にnonnullとか付けるべきではないとも言えます(強気)。
homebrewで簡単に入るので、ぜひおためしください。
1.7の話
1.7では、検査したいクラスのフィルタに正規表現が書けるようになりました。nullfilter
に
/ViewController/
などと書くと、クラス名にViewController
を含むものだけ検査するようになります。
本当は、negationが書きたくて、例えば
!/ViewController/ !/^NS/
などと書いて「ViewControllerとNSなんとか以外のクラスを検査する」としたいのですが、フィルタの意味を考え込んでしまってまだできていません。