iosswiftuitableviewgenerics

Error when trying to use generic UITableViewCell


I'm trying to make a reusable UITableView. I will pass in generics for item and UITableViewCell. However am having an error when I try to cast my cell to C and am not sure how else to fix this.

Member 'reusableLoadMoreTableView' cannot be used on value of type 'any SharedLoadMoreTableViewDelegate<T, C>'; consider using a generic constraint instead

protocol SharedLoadMoreTableViewDelegate<T, C>
{
    associatedtype T
    associatedtype C: UITableViewCell
    
    func reusableLoadMoreTableView(configure cell: C, for item: T)
}


class ReusableLoadMoreTableView<T, C: UITableViewCell>: UIView, UITableViewDelegate, UITableViewDataSource
{   
    private let tableView = UITableView()
    private var items: [T] = []
    
    var delegate: (any SharedLoadMoreTableViewDelegate<T, C>)?
    
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
     {
        let cell = tableView.dequeueReusableCell(withIdentifier:"CustomTableViewCell", for: indexPath) as! C
            
        if indexPath.row < items.count 
         {
            delegate?.reusableLoadMoreTableView(configure: cell, for: items[indexPath.row])
         }
            
           return cell
      }
    
  }

Solution

  • As the compiler suggests, you should consider SharedLoadMoreTableViewDelegate as a generic constraint instead of a type

    protocol SharedLoadMoreTableViewDelegate<T, C>
    {
        associatedtype T
        associatedtype C: UITableViewCell
        
        func reusableLoadMoreTableView(configure cell: C, for item: T)
    }
    
    
    class ReusableLoadMoreTableView<LoadMoreT: SharedLoadMoreTableViewDelegate>: UIView, UITableViewDelegate, UITableViewDataSource
    {
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            0
        }
        
        private let tableView = UITableView()
        private var items: [LoadMoreT.T] = []
        
        var delegate: LoadMoreT?
        
         func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
         {
             let cell = tableView.dequeueReusableCell(withIdentifier:"CustomTableViewCell", for: indexPath) as! LoadMoreT.C
                
            if indexPath.row < items.count
             {
                delegate?.reusableLoadMoreTableView(configure: cell, for: items[indexPath.row])
             }
                
               return cell
          }
        
      }
    

    Your code is also not compiling in the old version of swift that you are using. Since the implementation of SE-0352, it will compile properly. My advice is to update your swift version by updating XCode version or installing a newer swift installation onto your machine to match or exceed Swift 5.7