なにがうざいかと言うと、なかったら作る処理が簡潔に書けない。
コードオンリーでUITableViewを作っていると、UITableViewCellを作るときにdequeueReusableCellメソッドがnilを返した場合に新しくインスタンスを作り、nilでなければメソッドより返された値を使う。
??演算子を使用すれば、それに近いことはできる。だがしかし、新たに作成したUITableViewCellの初期設定がしたいのだ。??の後ろが1行じゃ足りなくて、もう少し行が欲しい。
Objective-Cの場合、至ってシンプルである。nilだったら作って設定すればいい。
- let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "hoge") ?? UITableViewCell(style: .default, reuseIdentifier: "hoge")
- - (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"hoge"];
- // 再利用セルがない場合は
- if( cell == nil ) {
- // 作成する
- cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"hoge"];
- // ここで作ったcellの共通設定
- }
- // ここで内容の更新処理
- return cell;
- }
Swiftの場合、guard文だと処理の中断が必須なため。guard文の中と外で2回内容の更新処理を書かなくてはならなくなる
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- guard let cell = tableView.dequeueReusableCell(withIdentifier: "hoge") else {
- let cell = UITableViewCell(style: .default, reuseIdentifier: "hoge")
- // 初期設定
- // 内容の更新処理
- return cell
- }
- // 内容の更新処理
- return cell
- }
オプショナルバインディングだと大した処理がないのに、代入のためだけのif-else両方が必要になる
外のスコープに変数を用意するぐらいだったら、オプショナルバインディングなどいらぬ。
- let cell:UITableViewCell
- if let unwrappedCell = tableView.dequeueReusableCell(withIdentifier: "hoge") {
- cell = unwrappedCell
- } else {
- cell = UITableViewCell(style: .default, reuseIdentifier: "hoge")
- // 初期設定
- }
- // 内容の更新処理
- return cell
以下のようにオプショナル構文を使わないで書いたって同じことだ。
わずかではあるが、変数を2個用意しないで済むオプショナルバインディングを使った方が簡潔なのがなんか腹立たしい。
- // セルの再利用可能か取得して見る
- let optCell:UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "hoge")
- let cell:UITableViewCell
- if optCell == nil {
- cell = UITableViewCell(style: .default, reuseIdentifier: "hoge")
- // 初期設定をする
- } else {
- // アンラップする
- cell = optCell!
- }
- // 内容の更新処理をする
- return cell
内容の更新処理をメソッド化すれば2回同じことは書かないで済むし、UITableViewCellのサブクラスを作れば??演算子でいけますが、だがObjective-Cと同じことができないのがなんかうざい。
??演算子の後ろにすぐ実行するUITableViewCellを戻り値とするクロージャ書いたらなんかできそうな気がするも、邪道な感じがして試したくもない。
とりあえず外のスコープの変数用意しておいて、オプショナルバインディグが正攻法かなと思う。