从 uiviewcontroller 操作 uicollectionviewcell 内的 uicollectionview

Posted

技术标签:

【中文标题】从 uiviewcontroller 操作 uicollectionviewcell 内的 uicollectionview【英文标题】:Manipulate uicollectionview inside uicollectionviewcell from uiviewcontroller 【发布时间】:2018-08-29 01:04:05 【问题描述】:

我有一个 UIViewController 包含一个 UICollectionView 并且在他们的 UICollectionViewCell 中嵌入了另一个 UICollectionView structure

视觉上看起来像这样: visually

我想在 UIViewController 中按下 BOTON,然后在外部 UICollectionView 的单元格内更改 UICollectionView 的 backgroundColor

我的 UIViewController 类

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)



我的 UICollectionViewCell 类

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



我看到了另一个与我的问题类似的帖子,但我不知道如何继续How to access a collectionView that is embedded in a parent collectionViewCell in the main UIViewController?

【问题讨论】:

【参考方案1】:

在你的情况下,你没有设置你创建的委托,你应该在里面设置它:

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

另外,为了避免reference-cycle 将您的delegateExterior 指针设置为弱:

weak var delegateExterior: ExteriorCollectionViewCellDelegate?

另一种解决方案是在ExteriorCollectionViewCell 内添加一个observer,当点击按钮并在UIViewController 内调用IBAction 方法时,使用post notification 传递该事件进入你的观察者。

即:

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()

在 IBAction 方法中从 IBAction 发送通知事件:

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

但是如果按钮在您的 UICollectionViewCell 内,您可以在 UICollectionViewCell 内使用 IBAction 方法并在那里执行您的逻辑。

【讨论】:

以上是关于从 uiviewcontroller 操作 uicollectionviewcell 内的 uicollectionview的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5 从 pyuic5 转换文件或 uic.loadUi 调用 gui

Xcode 水平 UIScrollView

用户界面编译器 (Uic) qt3 与 qt4/5,impl 参数等价

使用 pyuic 与 uic.loadUi 的好处

如何使用 setupUi 或 uic 输出来创建没有父小部件的独立布局?

从 AppDelegate 添加 3D Touch 快速操作