想要从容器视图推送到另一个视图控制器

Posted

技术标签:

【中文标题】想要从容器视图推送到另一个视图控制器【英文标题】:Want to push to another view controller from a container view 【发布时间】:2017-10-02 09:38:22 【问题描述】:

我有什么:带有一些“子/容器”视图的视图控制器 (WhereViewController)。一种是集合视图(typeCollectionView)。 WhereViewController 嵌入在 navigationController 中: Screenshot

class WhereViewController: UIViewController 

lazy var progressContainerView: ProgressBarView = 
    let containerView = ProgressBarView(frame: CGRect(x: 0, y: 0, width: 0, height: 0))

    containerView.translatesAutoresizingMaskIntoConstraints = false

    return containerView
()

let questionLabel: UILabel = 
    let label = UILabel()

    label.text = "question?"
    label.textAlignment = NSTextAlignment.center
    label.font = UIFont.init(name: "OpenSans-Italic", size: 14)
    label.textColor = UIColor(red:0.33, green:0.33, blue:0.33, alpha:1.0)
    label.translatesAutoresizingMaskIntoConstraints = false

    return label
()

let typeCollectionView: WhereCollectionView = 
    let collectionView = WhereCollectionView(frame: CGRect(x: 0, y: 0, width: 0, height: 0))

    collectionView.translatesAutoresizingMaskIntoConstraints = false

    return collectionView
()

override func viewDidLoad() 
    super.viewDidLoad()

    navigationItem.title = "Schaden melden"

    view.backgroundColor = UIColor.white


    view.addSubview(progressContainerView)
    view.addSubview(questionLabel)
    view.addSubview(typeCollectionView)

    setupProgressContainerView()
    setupQuestionLabel()
    setupTypeCollectionView()


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


private func setupProgressContainerView() 
    progressContainerView.topAnchor.constraint(equalTo: view.topAnchor, constant: 60).isActive = true
    progressContainerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    progressContainerView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    progressContainerView.heightAnchor.constraint(equalToConstant: 50).isActive = true


private func setupQuestionLabel() 
    questionLabel.topAnchor.constraint(equalTo: progressContainerView.bottomAnchor, constant: 22).isActive = true
    questionLabel.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    questionLabel.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    questionLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true


private func setupTypeCollectionView() 
    typeCollectionView.topAnchor.constraint(equalTo: questionLabel.bottomAnchor, constant: 20).isActive = true
    typeCollectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    typeCollectionView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    typeCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

我想要做什么: 在 typeCollectionView 中:如果选择了一个项目 (didSelectItemAt),我想通过 WhereViewController 的 navigationController 推送到下一个 viewController。我的 typeCollectionView 看起来像:

class WhereCollectionView: UICollectionView, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource 

var whereViewController: WhereViewController?

let label = ["x", "y", "z"]

override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) 
    let layout = UICollectionViewFlowLayout()
    super.init(frame: CGRect.zero, collectionViewLayout: layout)

    backgroundColor = UIColor.white

    delegate = self
    dataSource = self

    self.register(WhereCollectionViewCell.self, forCellWithReuseIdentifier: "WhereCollectionViewCell")


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


func numberOfSections(in collectionView: UICollectionView) -> Int 
    // #warning Incomplete implementation, return the number of sections
    return 1



func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    // #warning Incomplete implementation, return the number of items
    return label.count


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

    cell.injureLabel.text = label[indexPath.row]

    return cell


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


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


我已经尝试将 whereViewController 赋予 typeCollectionView:

let typeCollectionView: WhereCollectionView = 
    let collectionView = WhereCollectionView(frame: CGRect(x: 0, y: 0, width: 0, height: 0))

    collectionView.translatesAutoresizingMaskIntoConstraints = false
    collectionView.whereViewController = self 

    return tableView
()

但得到:无法将类型“(NSObject)->()-> WhereViewController”的值分配给类型“WhereViewController?”

有人可以帮我吗?还是不能与 collectionView (containerView) 中的 navigationController “对话”?

我不使用故事板

【问题讨论】:

【参考方案1】:

尝试:

1) 添加扩展:

extension UIView 

   var parentViewController: UIViewController? 
      var parentResponder: UIResponder? = self
      while parentResponder != nil 
         parentResponder = parentResponder!.next
         if parentResponder is UIViewController 
            return parentResponder as! UIViewController!
         
      

      return nil
   

2) 现在你可以使用:

parentViewController?.present(<ControllerName>, animated: true)

希望对你有帮助

【讨论】:

【参考方案2】:

您应该使视图控制器符合集合委托方法,而不是集合视图本身

使WhereViewController符合UICollectionViewDataSourceUICollectionViewDelegateUICollectionViewDelegateFlowLayout

class WhereViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout

WhereViewControllerviewDidLoad方法中,设置委托和数据源:

override func viewDidLoad() 
    super.viewDidLoad()

    typeCollectionView.dataSource = self
    typeCollectionView.delegate = self

    [...]

【讨论】:

我已经实现了代码,在:“(typeCollectionView.collectionViewLayout as?UICollectionViewFlowLayout)?.delegate = self”我有一个错误:“'UICollectionViewFlowLayout'类型的值没有成员'委托”。【参考方案3】:

在这里您可以使用委托将消息从CollectionView 发送到 ViewController.

简单地声明一个协议

protocol CustomDelegate: class 
    func collectionView(DidSelect : Int)

然后在WhereCollectionView类中创建一个CustomDelegate协议的实例

class WhereCollectionView: UICollectionView 

weak var customDelegate:CustomDelegate?


didSelect 方法中触发委托方法

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
   if let _del = customDelegate 
         _del.collectionView(DidSelect : IndexPath.row)



ViewController 中,您将在viewcontroller 中添加collectionviewdelegate 设置为self

override func viewDidLoad() 
    super.viewDidLoad()

    navigationItem.title = "Schaden melden"

    view.backgroundColor = UIColor.white

   typeCollectionView.customDelegate = self

    view.addSubview(progressContainerView)
    view.addSubview(questionLabel)
    view.addSubview(typeCollectionView)

    setupProgressContainerView()
    setupQuestionLabel()
    setupTypeCollectionView()

同样在ViewController中实现Custom委托方法

func collectionView(DidSelect : Int) 
   /// from there you can do your job

【讨论】:

我尝试遵循您的代码。此时:weak var delegate:CustomDelegate?我收到一个错误,说:“属性 'delegate' 类型为 'CustomDelegate?'无法覆盖类型为 'UICollectionViewDelegate?' 的属性";你能帮忙吗? 你得到这个错误 UICollectionView 已经有委托变量。只需更改 CustomDelegate 变量的名称,您的问题就会得到解决。

以上是关于想要从容器视图推送到另一个视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

推送到另一个选项卡的视图控制器

ios - 推送到另一个视图控制器时,应用程序 UI 会阻塞一段时间

将另一个视图控制器推送到 UITabBarController 视图中

如何将新的 viewController 推送到另一个视图控制器中的现有视图中?

将视图控制器从根推送到详细视图控制器 (SplitView)

将视图控制器推送到另一个视图控制器时如何处理 UIParallaxDimmingView?