繁体   English   中英

委托从模态呈现的视图控制器传回数据

[英]Delegation to pass data back from modally presented view controller

假设我们有两个视图控制器,一个带有标签的父视图和一个带有表格视图的模态呈现的子视图。 我如何使用委托将用户在表视图中的选择传递回父级?

视图控制器1:

   var delegate: vc2delegate?

   override func viewDidLoad {
        super.viewDidLoad()
        let label.text = ""
   }

视图控制器2:

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
           return 5
       }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell
            let selections = ["1", "2", "3", "4", "5"]
            cell.selections.text = selections[indexPath.row]
            return cell
       }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let cell = tableView.cellForRow(at: indexPath) as? Cell {
            cell.didSelect(indexPath: indexPath as NSIndexPath)

            }

        dismiss(animated: true, completion: nil)
        } 
   //wherever end of class is

   protocol vc2delegate {
      // delegate functions here
   }

我什至有正确的方法吗? 我从来没有真正理解过这种模式,我认为学习 iOS 对我来说至关重要。 另一个棘手的警告可能是当您关闭模式视图控制器时不会调用 viewDidLoad() 。

看看 UIViewController 生命周期文档: ViewDidLoad 只被调用一次。

有很多关于如何执行此操作的指南,只需快速搜索即可。 您需要更新 dataSource 逻辑,因为我添加了一个快速字符串数组,您很可能会有更复杂的东西,但想法仍然相同。

顺便说一句,我使用了您的 vc1/vc2 命名约定,但我希望您的控制器名称更有意义。

在您的代码中,您在错误的 VC 上拥有委托。 这是它应该是什么样子的快速代码示例:

class VC1: UIViewController {

    let textLabel = UILabel()

    // whenever you're presenting the vc2
    func presentVC2() {
        var vc2 = VC2()
        vc2.delegate = self
        self.present(vc2, animated: true, completion: nil)
    }
}

extension VC1: VC2Delegate {
    func updateLabel(withText text: String) {
        self.textLabel.text = text
    }
}


protocol VC2Delegate: class {
    func updateLabel(withText text: String)
}

class VC2: UIViewController {
    weak var delegate: VC2Delegate?
    let dataSource = ["string 1", "tring 2"]
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let string = dataSource[indexPath.row]
        self.delegate?.updateLabel(withText: string)
        dismiss(animated: true, completion: nil)
    }
}

您也可以使用回调函数从 tableview 更新您的标签:

1)VC2 中声明回调函数:

var callback:((String) -> Void)?

2)VC2 的tableview CellForRowAt 方法中调用此函数:

let dataSource = ["string 1", "tring 2"]

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      let string = dataSource[indexPath.row]  
      var cell = tableView.dequeueReusableCell(withIdentifier: "yourCell") as! YourCell

     //here you can call callback function & pass string to VC1
     cell.callback?(dataSource[indexPath.row])
}

3)现在你可以在任何你调用 VC2 的地方调用VC1中的回调闭包:

class VC1: UIViewController {

    let textLabel = UILabel()

    //I'm calling this(presentVC2()) function on ViewDidLoad you can call anywhere you want
    func viewDidLoad() {
        super.viewDidLoad()
        presentVC2()
    }

    // whenever you're presenting the vc2
    func presentVC2() {
        var vc2 = VC2()
        vc2.callback = { text in
            self.textLabel.text = text
        }
        self.present(vc2, animated: true, completion: nil)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM