简体   繁体   中英

Manipulate uicollectionview inside uicollectionviewcell from uiviewcontroller

I have a UIViewController containing a UICollectionView and within their UICollectionViewCell is embedded another UICollectionView structure

And visually looks like this: visually

I want to press BOTON in UIViewController and from there, change the backgroundColor of UICollectionView inside the cell of the outter UICollectionView

My UIViewController class

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {


@IBOutlet weak var scrollH: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    if let flowLayout = scrollH.collectionViewLayout as? UICollectionViewFlowLayout {
        flowLayout.minimumLineSpacing = 0
    }

    setupMenuQuestion()
}

var uiview: UIView = {
    let view1 = UIView()
    view1.backgroundColor = UIColor.brown
    return view1
}()

var uibutton: UIButton = {
    let btn1 = UIButton()
    btn1.setTitle("BOTON", for: .normal)
    btn1.addTarget(self, action: #selector(presionoBoton), for: .touchUpInside)
    return btn1
}()

@objc func presionoBoton() {
    delegateExterior?.cambiarBackground()
}

var delegateExterior: ExteriorCollectionViewCellDelegate?

private func setupMenuQuestion() {
    view.addSubview(uiview)

    uiview.translatesAutoresizingMaskIntoConstraints = false
    uiview.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
    uiview.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
    uiview.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
    uiview.heightAnchor.constraint(equalToConstant: 30).isActive = true

    uibutton.translatesAutoresizingMaskIntoConstraints = false
    uiview.addSubview(uibutton)
    uibutton.centerYAnchor.constraint(equalTo: uiview.centerYAnchor).isActive = true
    uibutton.centerXAnchor.constraint(equalTo: uiview.centerXAnchor).isActive = true
    uibutton.leftAnchor.constraint(equalTo: uiview.leftAnchor, constant: 7).isActive = true
    uibutton.rightAnchor.constraint(equalTo: uiview.rightAnchor, constant: -7).isActive = true
    uibutton.heightAnchor.constraint(equalTo: uiview.heightAnchor, multiplier: 0.8).isActive = true

}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 3
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cellNumQuestion = collectionView.dequeueReusableCell(withReuseIdentifier: "celdaExterior", for: indexPath) as! ExteriorCollectionViewCell
    return cellNumQuestion
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width, height: view.frame.height - 100)
}

}

My UICollectionViewCell Class

protocol ExteriorCollectionViewCellDelegate {
func cambiarBackground()
}

class ExteriorCollectionViewCell: UICollectionViewCell, 
UICollectionViewDataSource, UICollectionViewDelegate, 
UICollectionViewDelegateFlowLayout, ExteriorCollectionViewCellDelegate{

func cambiarBackground() {
    collectionCelda.backgroundColor = UIColor.black
}

@IBOutlet weak var collectionCelda: UICollectionView!


override init(frame: CGRect) {
    super.init(frame: frame)
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.minimumInteritemSpacing = 40
    layout.minimumLineSpacing = 40
    collectionCelda!.collectionViewLayout = layout

}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 4
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    var cell = UICollectionViewCell()
    cell = collectionView.dequeueReusableCell(withReuseIdentifier: "celdaInterior", for: indexPath)

    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: frame.width - 20, height: 400)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

    return UIEdgeInsets(top: 30.0, left: 0.0, bottom: 30.0, right: 0.0)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 40
}

}

I have seen another post similar to my problem but I do not know how to proceed
How to access a collectionView that is embedded in a parent collectionViewCell in the main UIViewController?

In your case, you didn't set the delegate you've created, you should set it inside:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cellNumQuestion = collectionView.dequeueReusableCell(withReuseIdentifier: "celdaExterior", for: indexPath) as! ExteriorCollectionViewCell
    // Setting the delegate
    delegateExterior = cellNumQuestion
    return cellNumQuestion
}

Also, in order to avoid reference-cycle set your delegateExterior pointer to be weak:

weak var delegateExterior: ExteriorCollectionViewCellDelegate?

Another solution will be to add an observer inside ExteriorCollectionViewCell and when the button is tapped and the IBAction method gets called inside your UIViewController , use post notification to pass that event into your observer.

ie:

Add the observer that will listen to your events inside your ExteriorCollectionViewCell :

 NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "EventForCollectionView"),
                                                               object: nil,
                                                               queue: nil) { [weak self] (_) in
// This method will be invoked when you post notification from your IBAction method inside your UIVC                                                                
self?.YourCustomMethod()
}

Send your notification event from your IBAction inside the IBAction method:

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "EventForCollectionView"), object: nil)

But if the button is inside your UICollectionViewCell you can just use IBAction method inside your UICollectionViewCell and do your logic there.

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