たしかに、
Swift
1 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
2 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ProfileCell
3 return cell
4 }
このコードだけ実行しても、ダウンキャストの意味はわからないと思います。
また、ダウンキャストさせる型である ProileCell
の作りによっては、ダウンキャストをしなくても動作には影響がない可能性もあります。
そういう意味では、ここで無理にダウンキャストする必要はありません。
しかし、たとえば次の様な型を考えてみたいと思います。
Swift
1class ProfileCell: UICollectionViewCell {
2 var text: String = ""
3}
上記のコードは、CollectionView に表示させるためのカスタムセルの例です。
本来はもっと色々な処理を入れることもありますが、説明を簡単にするためにあえてプロパティを一つのみにしておきたいと思います。
ここで重要なのは、ProfileCell
というカスタムクラス(独自の型)は、UICollectionViewCell
を継承している、ということです。
つまり、UICollectionViewCell
の様々なプロパティやメソッドを引き継いだ上で、新たにtext
というプロパティを含んだ型を ProfileCell
として作った、と考えていいと思います。
その後、このカスタムクラスを CollectionView のセルとして利用するため、
Swift
1 collectionView.register(ProfileCell.self, forCellWithReuseIdentifier: "cell")
このような感じで登録することになります(StorBoardで登録させた場合には、このコードは必ずしも出てくるわけではありません)。
さて、ここで登録したセルは、実際に表示する際に呼び出す必要があるのですが、その時に使うメソッドが
Swift
1 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
の一行になるわけです。
ただし、注意したいのは、dequeueReusableCell(withReuseIdentifier:for:)
というメソッドの戻り値は、UICollectionViewCell
という型である、という点です。
Dequeues a reusable cell object located by its identifier.
上記のリファレンスを読んでいただいてもいいと思いますし、Xcode のヘルプ機能を使っても見ることができるので、一度見てみていただけますでしょうか。
さて、上記のメソッドが返す型は UICollectionViewCell
です。なので、実は最初に登録した ProfileCell
という型として見えていない、という問題が発生します。
具体的に何が起きるかというと、下記の様なコードを実行しようとした場合に、コメントした部分でエラーが出てしまいます。
Swift
1 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
2 cell.text = "abcde" // ここでエラーになる
登録した時には ProfileCell
というクラスで登録し、そのクラスには text
というプロパティがあるにもかかわらず、それを見ることができないわけです。
dequeueReusableCell(withReuseIdentifier:for:)
は UICollectionViewCell
というクラスしか返さないため、どうにかして ProfileCell
として利用する方法を考える必要があります。
その時に使う演算子が、ダウンキャスト演算子(as?
もしくはas!
)となるわけです。
ダウンキャストするというのはどういうことかというと、与えられた元の型(スーパークラスや親クラスと言ったりします)を、そのクラスを引きついたサブクラスとして変換する処理のことです。
つまり、下記のようにダウンキャストを入れることによって、クラスの依存関係を適切に変更することができるようになる、という仕組みです。
Swift
1 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ProfileCell
2 cell.text = "abcde" // エラーは出ないし、Xcode の補完も効くようになる
ちなみに、ダウンキャストは必ずしも成功するとは限りません。
クラスに継承関係がある場合には成功しますが、継承関係にないクラスの間でダウンキャストを行うと失敗するようになっています(as?
で処理するか、as!
で処理するかによって失敗時の挙動がことなります)。
なぜ失敗を知る必要があるのか、という話になると、これまた適用場面も考え方も違ってきますのでここでは省きますが、とりあえずダウンキャストというのは、このような目的で使っている、とう点だけ抑えていただければと思います。