How to reference a UICollectionView from other custom UICollectionViewCells

699 views Asked by At

I have a UIViewController that has a UICollectionView with 4 custom cells. In one of the cells I have a UIButton that when tapped needs to access another one of the cells, to update an UIImage. How do I reference the collectionView reference in my UIViewController to pass it to the other NIB's?

//CollectionView
@IBOutlet weak var collectionView: UICollectionView!

Do I put something in my override func awakeFromNib() in order to reference the other cells?

Example:

let myCell = collectionView!.cellForItem(at: myIndexPath) as! MainCollectionViewCell

How do I reference collectionView from other NIB's?

Thanks

1

There are 1 answers

2
Daniel T. On

From an architectural perspective, the answer is "you don't."

The correct answer is to have a Model class, probably with properties that represent different parts of the model. When the user taps the button, it affects the model in some way (the button action should call a method on a model object. The method's name would be something that would make sense to the user of the app.)

When the model changes state, it should notify any Observers. Look up the Observer pattern, but basically, it's like an array of delegates.

The cell with the UIImage should be set up to observe the model and react to changes in the model which in this case happened to be due to the button tap, but could have occurred through other means as well.

First you need a model class:

class MyModel {
    typealias Observer = (MyModel) -> Void

    func add(observer: @escaping Observer) {
        observers.append(observer)
    }

    func updateImage() {
        // do what you need to do to update `myImage`
        // then call:
        update()
    }

    private (set) var image: UIImage?
    private var observers = [Observer]()

    private func update() {
        for each in observers {
            each(self)
        }
    }
}

Then make an instance of this model in your view controller:

let model = MyModel()

Now pass your view controller's model to each of the cells inside the cellForItemAt method.

cell.model = model

In the cell that has the image, you give it a model property like this:

var model: MyModel! {
    didSet {
        model.add(observer: { [weak self] updated in 
            self?.imageView.image = updated.image
        })
    }
}

The cell that has the button would have a normal model property and in the IBAction for the button, you would call model.updateImage().

var model: MyModel!

@IBAction func buttonTapped(_ sender: Any) {
    model.updateImage()
}