1

I'm working with a collection view, and I'm trying to make a array of tuples, containing the reuse identifier, the cell's type, and the function to call to set up the cell in tableView(_:cellForItemAt:).

So far so good, except for the function. Xcode complains in the array's declaration that it

"Cannot convert value of type '(AddASpotInfoVC) -> (UICollectionViewCell) -> UICollectionViewCell' to expected element type '(UICollectionViewCell) -> UICollectionViewCell'

AddASpotInfoVC is the view controller's class. Here's the array's initialization itself:

typealias cellFunc = (_ aCell: UICollectionViewCell) -> UICollectionViewCell
let reuseIdentifiers: [(String, UICollectionViewCell.Type, cellFunc)] = [
    ("AddASpotInfoPicCell", AddASpotInfoPicCell.self, picCellFunc),
    ("AddASpotInfoNameCell", AddASpotInfoNameCell.self, nameCellFunc),
    ("AddASpotInfoDescCell", AddASpotInfoDescCell.self, descCellFunc),
    ("AddASpotInfoTagsCell", AddASpotInfoTagsCell.self, tagCellFunc)]

And all the functions in the array (for now) are in an extension of the view controllers' class (not that it should be relevant, I think...) and look like this

func picCellFunc(aCell: UICollectionViewCell) -> UICollectionViewCell {
    return aCell
}

So, what am I doing wrong in my array's initialization?

jscs
  • 63,694
  • 13
  • 151
  • 195
ElFitz
  • 908
  • 1
  • 8
  • 26
  • 1
    Try removing all but one array element, and adding them back one by one, to see whether it's a problem with some or all of them. – Jim Matthews Dec 02 '16 at 21:11
  • AddASpotInfoPicCell.Type is not equal UICollectionViewCell.Type. Its a different type. – shallowThought Dec 02 '16 at 21:15
  • 1
    The problem is that you cannot use the instance method in the initialization of the `reuseIdentifiers` variable. You can move the initialization to a method (e.g. viewDidLoad) or make it a lazy property. Compare http://stackoverflow.com/questions/25855137/viewcontroller-type-does-not-have-a-member-named, http://stackoverflow.com/questions/25854300/how-to-initialize-properties-that-depend-on-each-other, http://stackoverflow.com/questions/39867568/initialize-lazy-instance-variable-with-value-that-depends-on-other-instance-vari for similar (not identical) problems. – Martin R Dec 02 '16 at 21:17
  • @shallowThought : AddASpotInfoPicCell is a subclass of UICollectionViewCell, declared as `class AddASpotInfoPicCell: UICollectionViewCell { }`, so it's good – ElFitz Dec 03 '16 at 17:38
  • @JimMatthews Yup, built the array's tuple progressively, everything just went haywire when I added the functions ^^ But thanks ! :-) – ElFitz Dec 03 '16 at 17:40

2 Answers2

2

Function implementation can depend on other variables. So it requires you to declare functions as static. Use:

static func picCellFunc (aCell: UICollectionViewCell) -> UICollectionViewCell

Inside your array use:

AddASpotInfoVC.picCellFunc

Edit: You can also move array initialisation code into one of your functions or initialisers.

Adamsor
  • 730
  • 1
  • 6
  • 14
1

If your functions are not using any state, it does make sense to make them class or static methods like Adamsor suggests.

But if you do want your methods to read/write any variables in your viewController instance, you can use a lazy var for the tuple array, and reference the methods using self, like this:

lazy var reuseIdentifiers: [(String, UICollectionViewCell.Type, cellFunc)] = [
    ("AddASpotInfoPicCell", AddASpotInfoPicCell.self, self.picCellFunc),
    ("AddASpotInfoNameCell", AddASpotInfoNameCell.self, self.nameCellFunc),
    ("AddASpotInfoDescCell", AddASpotInfoDescCell.self, self.descCellFunc),
    ("AddASpotInfoTagsCell", AddASpotInfoTagsCell.self, self.tagCellFunc)]
marosoaie
  • 2,352
  • 23
  • 32
  • Hadn't thought of it. But when lazy loading, couldn't the array not be initialized when it's called by the CollectionViewDataSource methods ? – ElFitz Dec 03 '16 at 17:41
  • It will allways be initialized the first time you call it: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID257 – marosoaie Dec 03 '16 at 17:44
  • Good to know ! One thing though, for future readers, seems like Swift (at least Swift3) doesn't allow for lazy let. Has to be var. – ElFitz Dec 03 '16 at 17:51