LoginSignup
1
1

More than 3 years have passed since last update.

UITableViewとUICollectionViewにおいてFallbackする方法

Posted at

環境

Xcode: Version 11.3.1 (11C505)
Swift: 5
iOS: 13.2

執筆きっかけ

先輩から「その方法ではUICollectionViewの場合はクラッシュするよ」と指摘されたので検証する

その当時のフォールバック方法

*一部省略しております


 final class TableViewController: UIViewController {
     var mockError: String? // エラーを模しています

     private lazy var tableView: UITableView = {
             ・・・
            ・・・
             tableView.register(UITableViewCell.self, forCellReuseIdentifier: NSStringFromClass(UITableViewCell.self))
             return tableView
         }()
 ・・・
 ・・・
 }

 extension TableViewController: UITableViewDataSource {
 ・・・
 ・・・
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         guard mockError != nil else {
             return UITableViewCell() // これが実行される
         }

         return tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(UITableViewCell.self), for: indexPath)
     }

 }

上記の場合,mockErrorがnilであるため,

 guard mockError != nil else {
     return UITableViewCell()
 }

が実行されます.これは,Errorが発生した想定です.
TableViewの場合は,registerされていないCellを返してもクラッシュしません.

UICollectionViewの場合

*一部省略しております

 final class CollectionViewController: UIViewController {

     private lazy var collectionView: UICollectionView = {
         ・・・
        ・・・
         collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: NSStringFromClass(UICollectionViewCell.self))
         return collectionView
     }()

     var mockError: String?

 ・・・
 ・・・

 }

 extension CollectionViewController: UICollectionViewDataSource {
 ・・・
 ・・・

     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
         guard mockError != nil else {
             return UICollectionViewCell() // これが実行される
         }

         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(UICollectionViewCell.self), for: indexPath)
         cell.backgroundColor = .black
         return cell
     } 
 }

先程のコードをUICollectionViewに置き換えてみました.
上記を実行すると...

 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the cell returned from 
- collectionView:cellForItemAtIndexPath: does not have a reuseIdentifier 
- cells must be retrieved by calling 
- dequeueReusableCellWithReuseIdentifier:forIndexPath:'

上記の通り,UICollectionViewの場合は,registerしたCell以外を返すとクラッシュします
よって,下記の用に書き換えます

 guard mockError != nil else {
     return collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(UICollectionViewCell.self), for: indexPath)
 }

まとめ

今後TableViewの仕様が変わる可能性も考えて,フォールバック時にはregisterしたCellをどちらも返すようにします

1
1
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
1
1