【问题标题】:How can I go about controlling 1 view controller from another?我怎样才能从另一个控制一个视图控制器?
【发布时间】:2018-01-19 23:25:36
【问题描述】:

所以我的 iOS 应用有以下布局。

我打算在purpleVC 中放置一个表格视图来控制Green viewcontroller...顶部peachVC 中将包含需要更改的文本。我只是不确定如何从另一个视图控制器控制一个视图控制器。这包括在单击 GreenVC 上的按钮时使紫色滑入和滑出。我知道有一些课程可以做到这一点,但我也想学习。

测试代表:

主视图控制器

import UIKit

protocol Purpleprotocol {
    func buttonpressed()
}

protocol Greenprotocol {

}

extension UIViewController {

    func alert(message: String, title: String = "") {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(OKAction)
        self.present(alertController, animated: true, completion: nil)
    }
}

class MainViewController: UIViewController,Purpleprotocol,Greenprotocol {
    weak var infoNav : UINavigationController?
    weak var greenVC: GreenVC?
    weak var purpleVC: PurpleVC?
    weak var peachVC: PeachVC?

    func buttonpressed() {
        alert(message: "This is message")
        print("buttonpressed")
        let date = Date()
        let calendar = Calendar.current
        let hour = calendar.component(.hour, from: date)
        let minutes = calendar.component(.minute, from: date)
        greenVC?.greenlabel.text = String(hour) + ":" + String(minutes)
    }

       override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "contentSegue" {
            let infoNav = segue.destination as! UINavigationController

        }
    }
}

PURPLEVIEW 控制器

class PurpleVC: UIViewController {

    var delegate: Purpleprotocol?

    @IBAction func butclick(_ sender: UIButton) {
        alert(message: "infunction")
        delegate?.buttonpressed()
           }


    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

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

谢谢 回复

【问题讨论】:

  • 不完全确定这是否可以通过导航控制器工作,我做了类似的事情,但从一个视图控制器直接到另一个视图控制器。本质上,想法是创建一个委托,并符合第二个 VC 中的委托。第一个 VC 在第二个 View 控制器中触发一个方法(以所需的方式控制它),然后当我想执行 segue 时,我会加载更改后的第二个 VC 并显示它。也许类似的东西可以帮助你。

标签: ios viewcontroller uicontainerview


【解决方案1】:

视情况而定,但看几个例子:

A) 您可以通过代理连接它。您的主视图控制器有 3 个子视图控制器,它应该向其报告更改。它还应该将自己作为委托分配给所有 3 个子控制器,在那里它将获得所有事件通知。这看起来像

func purpleViewController(sender: PVC, selectedItem: Item) {
    self.greenViewController.showItem(item: selectedItem)
    self.peachVC.showItem(item: selectedItem)
}

func purpleViewController(sender: PVC, shouldSetMenuClosed closed: Bool) {
    self.menuConstraint.constant = closed ? targetWidth : 0.0
}

B) 您可能有一个控制整个屏幕的数据模型,并为每个孩子设置一个委托。该模型将向其代表报告任何更改,以便他们做出相应的反应。主视图控制器将在加载时创建此模型的实例并将其传递给所有子视图控制器。然后孩子们将直接操纵模型:

在绿色控制器中:

func onTap() {
    mode.menuShown = !mode.menuShown
}

在模型中:

var menuShown: Bool = true {
    didSet {
        self.menuDelegate.model(self, changedMenuShownStateTo: menuShown)
    }
}

在主视图控制器中:

func model(_ sender: Model, changedMenuShownStateTo shown:Bool) {
    self.menuConstraint.constant = shown ? 0.0 : targetWidth
}

C)您可以使用通知,其中任何控制器都可以向通知中心发布自定义通知,而其他控制器可以观察通知并采取相应行动。

还有很多其他方法可以做到这一点,但这些可能是最受欢迎的。看看有没有适合你的...

【讨论】:

    【解决方案2】:

    代表团。

    您的MainViewController 将成为每个想要传回信息的嵌入式 VC 的代表。根据您的描述,您需要两个委托关系:

    protocol PurpleProtocol {
        func selected(row: Int, text: String)
    }
    
    protocol GreenProtocol {
        func slideButtonPressed()
    }
    

    让 MainViewController 实现这些协议。为 embed segues 提供标识符。您可以在 文档大纲 视图中找到它们。在 prepareForSegue 中,保留指向嵌入式 VC 的指针并将您自己作为委托传递:

    class MainViewController: UIViewController, PurpleProtocol, GreenProtocol {
        weak var greenVC: GreenViewController?
        weak var purpleVC: PurpleViewController?
        weak var peachVC: PeachViewController?
    
        func selectedRow(row: Int, text: String) {
            // do something useful
        }
    
        func slideButtonPressed() {
            // slide purple view in or out depending on current state
        }
    
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            if segue.identifier == "EmbedPurple" {
                let dvc = segue.destination as! PurpleViewController
                purpleVC = dvc
                dvc.delegate = self
            }
            else if segue.identifier = "EmbedGreen" {
                let nav = segue.destination as! UINavigationController
                let dvc = nav.topViewController as! GreenViewController
                greenVC = dvc
                dvc.delegate = self
            } else if segue.identifier = "EmbedPeach" {
                peachVC = segue.destination as! PeachViewController
            }
        }
    }
    

    在您的嵌入式 VC 中,添加一个 delegate 指针,并在适当的时候使用协议方法调用委托:

    class GreenViewController: UIViewController {
        weak var delegate: GreenProtocol?
    
        @IBAction slideButtonPressed(sender: UIButton) {
            delegate?.slideButtonPressed()
        }
    }
    
    class PurpleViewController: UITableViewController {
        weak var delegate: PurpleProtocol?
    
        override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            delegate?.selected(row: indexPath.row, text: modelArray[indexPath.row])
        }
    } 
    

    【讨论】:

    • 好的,我是新来的代表,所以大脑还没有完全在那里..那么我如何从紫色控制绿色......所以如果我点击紫色的按钮,我把VC换成绿色...
    • 当你点击紫色的一行时,它会调用MainViewController中的selectedRowselectedRow 可以使用greenVC 属性来调用GreenViewController 上的方法和设置属性。类似greenVC?.someProperty = valuegreenVC?.doSomethingUseful()
    • 啊,谢谢...最后一件事。如果我想将绿色换成其他视图控制器.....(这就是我将导航放在那里的原因)我打算将紫色作为“菜单”,而将绿色作为内容......
    • 在这种情况下,请在 MainViewController 中保留对 navCon 的引用。您可以将其存储在 prepareForSegue 中。然后你可以用navCon?.pushViewController推​​送一个新的VC。
    • 请在下面查看我的更新回复....无法让代理开火...
    猜你喜欢
    • 2018-04-13
    • 2016-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多