Swift 使用UITabBarController的自定义collectionView

Swift 使用UITabBarController的自定义collectionView,swift,uiview,swift3,uicollectionview,uicollectionviewcell,Swift,Uiview,Swift3,Uicollectionview,Uicollectionviewcell,我有一个自定义的ui视图,名为MenuBar。此菜单栏是一个自定义“选项卡栏”,其内部有一个包含5个单元格的collectionView。点击单元格时,我想显示一个ViewController,但我无法在我的didSelect方法中调用类似下面的代码,因为我无法访问当前函数: if indexPath.item == 1 { let dummyController = DummyController() present(dummyController, animated: tru

我有一个自定义的
ui视图
,名为
MenuBar
。此菜单栏是一个自定义“选项卡栏”,其内部有一个包含5个单元格的
collectionView
。点击单元格时,我想显示一个
ViewController
,但我无法在我的
didSelect
方法中调用类似下面的代码,因为我无法访问当前函数:

if indexPath.item == 1 {
    let dummyController = DummyController()
    present(dummyController, animated: true, completion: nil)
}
有人有解决办法吗?任何帮助都将不胜感激。谢谢你们。我的代码如下:

class MenuBar: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)  
        cv.backgroundColor = .clear
        cv.delegate = self
        cv.dataSource = self
        return cv
    }() 

    let seperatorView: UIView = {
        let view = UIView()
        view.backgroundColor = lightGray
        return view
    }()

    let imageNames = ["home_selected", "glimpse_selected", "camera_selected", "activity_selected", "profile_selected"]

    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(collectionView)
        addSubview(seperatorView)

        collectionView.register(MenuCell.self, forCellWithReuseIdentifier: "cellId")

        let selectedIndexPath = IndexPath(item: 0, section: 0)
        collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: .centeredHorizontally)

        _ = collectionView.anchor(self.topAnchor, left: self.leftAnchor, bottom: self.bottomAnchor, right: self.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)

        _ = seperatorView.anchor(collectionView.topAnchor, left: collectionView.leftAnchor, bottom: nil, right: collectionView.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 1)

        setupHorizontalBar()
    }

    var horizontalBarLeftAnchorConstraint: NSLayoutConstraint?

    func setupHorizontalBar() {
        let horizontalBarView = UIView()
        horizontalBarView.translatesAutoresizingMaskIntoConstraints = false
        horizontalBarView.backgroundColor = .darkGray
        addSubview(horizontalBarView)

        horizontalBarLeftAnchorConstraint = horizontalBarView.leftAnchor.constraint(equalTo: self.leftAnchor)
        horizontalBarLeftAnchorConstraint?.isActive = true

        horizontalBarView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

        horizontalBarView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1/5).isActive = true
        horizontalBarView.heightAnchor.constraint(equalToConstant: 4).isActive = true
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        let x = CGFloat(indexPath.item) * frame.width / 5
        horizontalBarLeftAnchorConstraint?.constant = x

        UIView.animate(withDuration: 0.45, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            self.layoutIfNeeded()
        }, completion: nil)
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! MenuCell

        cell.imageView.image = UIImage(named: imageNames[indexPath.item])?.withRenderingMode(.alwaysTemplate)

        return cell
    }

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

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

        return 0
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

为自定义视图定义委托,当拥有此视图的视图控制器创建委托时,它可以将自己设置为委托并处理演示文稿本身

例如

然后在创建菜单栏的视图控制器中执行以下操作:

menuBar.delegate = self
实现didSelectItem方法并在那里进行处理——实际上,您正在制作自己版本的Apple无处不在的委托模式,供他们在所有视图中使用。您可能希望将所选项目建模为indexPath以外的内容,但我不知道您的代码


我建议您总是将模型逻辑与视图逻辑解耦。例如,视图永远不应该知道它正在显示的模型,也不应该知道当用户与它交互时该做什么。这应该总是去耦合并转发。

我同意@Jeff的观点,模型逻辑应该总是从视图逻辑去耦合。但是,我最近实现了我自己的Tabbar,我是通过以下方式实现的:

  • 我在AppDelegate中实例化了一个
    UINavigationController
    ,这样我就可以从任何地方访问它
  • 然后,在自定义的
    菜单栏
    中,您可以通过调用
    (UIApplication.shared.delegate as AppDelegate)访问此navigationcontroller。您的navigationcontroller
    ,并使用它显示要显示的viewcontroller
  • 如果您确实希望将
    菜单栏
    用作
    UITabbarController
    ,则应始终将要显示为navigationcontroller的rootViewController的viewcontroller设置为如下所示:

    var appDelegate=UIApplication.shared.delegate作为?AppDelegate appDelegate?.YOURNAVIGATIONCONTROLLER?.ViewController=[(DummyController())!]


  • 希望这是有用的

    你能在上面的代码中提供一个例子吗?我是个新手。对不起,我很痛苦。谢谢你的回答!非常感谢。Top Man您只需将协议添加到菜单栏文件的顶部,然后将该属性添加到菜单栏。然后,无论您在何处创建菜单栏并将其添加到视图层次结构,都要将委托设置为该视图控制器,并在协议定义中实现所需的功能。目标C但相关
    menuBar.delegate = self