40
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOSAdvent Calendar 2015

Day 3

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

Last updated at Posted at 2015-12-03

最近のObjecitive-CにもSwiftに併せて細かな変更や機能追加がされており、NSArrayやNSDictionaryなどコンテナが保持する型を指定するLightweight Genericsが追加されたことも記憶に新しいですが、その他にも__kindofを型に指定するアノテーションが追加されていました。

2016年、Objective-Cのコードをまだまだ保守していく皆さんのために、今回はこの__kindofについて軽くまとめておきます。

はじめに結論

まず結論から書いておきます。今北産業です。

NSArray *array1;                   // 何が入ってるかわからん
NSArray<_kindof UIView *> *array2; // UIViewとそのサブクラス入ってる
NSArray<UIView *> *array3;         // UIViewしか入ってないもんね
  • add/setは何でもできるが「取り出すときにどうすべきか」で警告される。
  • __kindofを使わずに<UIView *>の場合はサブクラスでさえ入ってないという解釈のコードである
  • 戻り値にも__kindofが指定できるので、UITableViewCellやUIViewControllerなど継承して利用することが頻繁に行われるクラスには指定してインターフェースをより細かく作りこむことが出来る

Lightweight Genericsに__kindofを使うとどうなる?

そもそも__kindofがないと何が問題なのかを明確にするため、まず__kindofを使わずにArrayを作る

NSMutableArray<UIView *> *array = @[].mutableCopy;

それに対して要素を次のように2つ追加する。UIViewとUIImageView

[array addObject:[[UIView alloc] init]];
[array addObject:[[UIImageView alloc] init]];

これらをそれぞれ次のように取り出す

UIView *first = array[0];       // もちろんこれは何も問題ない
UIImageView *second = array[1]; // 警告される

ここでarray[1]をUIImageViewに代入しようとすると警告される。

以上をわざわざスクリーンキャプチャで見せると次のような感じ

スクリーンショット 2015-11-22 10.19.24.png

Lightweight Genericsを使ってコンテナに何が入っているかを明確にしたいが、実際はサブクラスが含まれている場合に警告されるようになっている。当然、キャストすれば警告はなくなるが、__kindofはサブクラスが入っていることを許可するために使われる。

NSMutableArray<__kindof UIView *> *array = @[].mutableCopy;
[array addObject:[[UIView alloc] init]];
[array addObject:[[UIImageView alloc] init]];
UIView *first = array[0];       // もちろんこれは何も問題ない
UIImageView *second = array[1]; // 警告されなくなる!!

しかし、まだ、__kindofの魅力はこんなもんじゃない

戻り値に__kindofを使うとどうなる?

もちろんメソッドの戻り値に__kindofを使うことも出来る。具体的にはUITableViewで頻繁に使う次のメソッドの戻り値にはすでに __kindof が使われている(Xcode7.1.1で確認)。

- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier
                                                   forIndexPath:(NSIndexPath *)indexPath;

(そう、つまりみなさんはすでに__kindofを使っていたのだ!!ΩΩΩ<な、なんだってー)

このインターフェースを見ると、再利用キューに保持されていた様々なUITableViewCellの派生クラスを取り出せるということが分かるし、実際にキャストする必要性がないということも分かりやすい(idを戻り値とするよりずっと分かりやすい)。

参考URL

https://developer.apple.com/videos/play/wwdc2015-401/
http://stackoverflow.com/questions/31399208/ios-kindof-nsarray

40
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?