简体   繁体   中英

How do I pass a value to a custom UICollectionViewCell?

I have a custom UICollectionViewCell that I am attempting to pass a value to from my view controller. I'm able to pass an image to the cell, but anything else comes up nil upon initialization.

Relevant code in the View Controller:

override func viewDidLoad() {

    self.collectionView!.registerClass(MyCustomCell.self, forCellWithReuseIdentifier: "Cell")

}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! MyCustomCell

    cell.someValue = 5
    cell.imageView.image = UIImage(named: "placeholder.png")

    return cell

}

In the custom cell class:

var someValue: Int!
var imageView: UIImageView!

override init(frame: CGRect) {

    super.init(frame: frame)

    imageView = UIImageView(frame: CGRectMake(0, 0, frame.width, frame.height))
    contentView.addSubview(imageView)

    let someValueLabel = UILabel()
    someValueLabel.frame = CGRectMake(0, 75, 200, 30)
    someValueLabel.text = "Value is: \(someValue)"
    self.addSubview(someValueLabel)
}

The image is successfully passed from the UICollectionView and I am able to display it, but 'someValue' is always nil.

What am I doing wrong?

The init method is called much earlier than you think it is -- within the dequeue process -- when the cell object is constructed. Part of initialization process is to attach the UIViews designed in Storyboard. So that image works because the UIImageView is already in place as a container during the Storyboard (NIB) loading process, and you're just setting its internal image property later.

You have correctly set the value of someValue for all future use, during cell rendering and event handling. So, for example, if there's an @IBAction handler that runs after the cell is displayed and tapped on, it will indeed have access to someValue . That's where your test print should go. What are you ultimately using someValue for?

FOLLOWUP

So it's a simple error; you just need to set the text value in cellForRowAtIndexPath . You don't need a copy of model data in the cell (ie no need to have a someValue field in your cell), either. Just configure the UI dynamically from your (properly separated) model data:

instead of:

cell.someValue = 5

You just need, eg:

cell.someValueLabel.text = "\(indexPath.row)" // or where ever you're getting your underlying model data from

It's a misconception to use init for any of this. The only responsibility of init for table cells is to allocate memory. A cell is a completely dynamic, temporary object, and all of its properties that reflect Application data must be set in the cellForRowAtIndexPath method. The visual rendering of the cell waits for the cellForRowAtIndexPath method to finish, so there's no timing problem.

Init method is called when the UICollectionView is instantiated. You're logging "someValue" in the init method and it's too early. Image is rendered since you're working to the ImageView directly that has already been instantiated. Try to log imageView.image in the init method, it should be nil too (or maybe not nil because the cell is reused).

You should make your job in custom variables setters and getters, where you're sure that they're not nil.

var someValue: Int!{
    didSet {
        print("Passed value is: \(newValue)")
    }
}

You are setting the value of someValue after the cell has been initialized.

You are calling print("Passed value is: \\(someValue)") during the initialization process.

Set a break point on the init method of your cell class. You should see it pass through there before you assign the value 5 to that variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM