Whilst coding in swift3 I wanted to use custom protocols and generics for reusing collection view cells. I know that this is the standard way of reusing cells:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TacoCell", for: indexPath) as? TacoCell {
cell.configureCell(taco: ds.tacoArray[indexPath.row])
return cell
}
return UICollectionViewCell()
}
But everytime I try to do this:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(forIndexPath: indexPath) as TacoCell
cell.configureCell(taco: ds.tacoArray[indexPath.row])
return cell
}
The compiler complains I have a "Missing argument for parameter 'for' in call"... The parameter in this case is "forIndexPath"
FYI...
I have custom extensions for reusing cells and loading nibs. Code is as follows:
ReusableView class
import UIKit
protocol ReusableView: class { }
extension ReusableView where Self: UIView {
static var reuseIdentifier: String {
return String.init(describing: self)
}
}
NibLoadableView class
import UIKit
protocol NibLoadableView: class { }
extension NibLoadableView where Self: UIView {
static var nibName: String {
return String.init(describing: self)
}
}
This is my extension for the UICollectionView
import UIKit
extension UICollectionView {
func register<T: UICollectionViewCell>(_: T.Type) where T: ReusableView, T: NibLoadableView {
let nib = UINib(nibName: T.nibName, bundle: nil)
register(nib, forCellWithReuseIdentifier: T.reuseIdentifier)
}
func dequeueReusableCell<T: UICollectionViewCell>(forIndexPath indexPath: NSIndexPath) -> T where T: ReusableView {
guard let cell = dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath as IndexPath) as? T else {
fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
}
return cell
}
}
extension UICollectionViewCell: ReusableView { }
The problem is that you've got a little bit of Swift 2.2 code alongside your Swift 3.0 code, and the compiler is getting confused when it tries to pick a method to call because nothing quite matches.
Your cellForItemAt
method calls your own dequeueReusableCell()
extension method with the IndexPath
from the collection view. However, the extension method you wrote expects to receive an NSIndexPath
, which is a subtly different thing.
Amend your extension method to this and the problem should clear up:
func dequeueReusableCell<T: UICollectionViewCell>(forIndexPath indexPath: IndexPath) -> T where T: ReusableView {