auto

これから iOS アプリを作る時は Swift 一択だと思いますが、Objective-C で作られた既存のプロジェクトをメンテナンスしないといけない場合もあると思います。

Objective-C から Swift への移行を円滑にするためには Nullability や Lightweight Generics への対応は必須です。1 Nullability は Implicitly Unwrapped Optional を回避できますし、Lightweight Generics は Array や Dictionary などの型が明示されるため、開発効率が上がります。

また、Objective-C から移行しない場合でも、コードの品質を向上させることができるため、Swift に移行する、しないに関わらず、対応すべきだと思います。

Nullability の対応

Nullability は、オブジェクトに nil を許可するかどうかを明示するものです。Swift であれば varlet に相当しますね。個別に nullable (nil を許可する)、nonnull (nil を許可しない) を定義してもよいのですが、NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END のマクロを使ってすべてのオブジェクトを nonnull 扱いにしてから、nil が入るものだけ nullable を定義するのがよさそうです。

ヘッダファイルに NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END を定義する

ヘッダファイルの #import の直後に NS_ASSUME_NONNULL_BEGIN を、最終行に NS_ASSUME_NONNULL_END を定義します。これで、NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END の間にあるオブジェクトの定義は、すべて nonnull 扱いになります。

#import "hogehoge.h"

NS_ASSUME_NONNULL_BEGIN

@interface Hoge: NSObject

@property ....

- (void)fugafuga;

@end

NS_ASSUME_NONNULL_END

nil になる可能性があるものに対して nullable を付与する

先の対応を行うと、すべてのオブジェクトは nil が入らないルールになっていますので、nil が入る可能性のものは個別に nulllable を付与していきます。個人的に、プロパティの nullable の位置は、一番最後にしています。

// プロパティ
@property (nonatomic, copy, nullable) NSString *title;

// メソッド
- (nullable NSSString *)stringByDate:(nullable NSDate *)date;

Lightweight Generics

Lightweight Generics は、配列や辞書に入れるオブジェクトの型を明示するものです。Swift であれば let titles: [String] のようにすると、String 型しか入らない配列になりますね。

Objective-C では今まで配列や辞書になんでも入れることができるのが辛いところだったので、やっとそれが解放されると思ったのですが、Lightweight とある通り、指定した型のオブジェクト以外を禁止するものではなく、ビルド時に警告が出るレベルのものです。それでも何もないよりは遥かにマシですが。ちなみに Swift は 指定した型以外のオブジェクトを入れることはできません。

型の追加

NSArrayNSDictionaryNSMutableDictionaryNSSet などに型を追加します。

// プロパティ
@property (nonatomic, copy, nullable) NSArray<NSString *> *titles;

// メソッド
- (nullable NSArray<NSIndexPath *> *)indexPathsForRowsInRect:(CGRect)rect;

__kindof について

指定した型のサブクラスが入る可能性がある場合、__kindof を付与します。

下の場合、UITableViewCell と、そのサブクラスを返す関数であることになります。

- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;

参考

Objective-CのLightweight Genericsに使われる__kindofとは何か - Qiita


  1. いっそ Swift で新しく作り直すという手もありますが…