Search code examples
swift3xcode8-beta6

"Missing argument for parameter 'for' in call"


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 { }

Solution

  • 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 {