协议委托快速到多个视图

时间:2018-01-27 16:27:36

标签: swift view controller delegates protocols

我正在努力学习关于代表的一切。在此示例中,主页面称为PagesTableViewController。当用户单击第1页时,它将获取DetailsViewController。当您填写标签时,您将返回PagesTableViewController。然后当按下Button时,它会将您带到PrintViewController并显示从DetailsViewController填充的标签。我一直在尝试教程和代码中的一些东西我一定做错了。

这是我的观点

enter image description here

这是PagesTableView的代码

import UIKit

class PagesTableViewController: UIViewController {

    let pages = ["Page 1","Page 2","Page 3"]

    @IBOutlet weak var pagesTableView: UITableView!


    override func viewDidLoad() {
        super.viewDidLoad()

        pagesTableView.dataSource = self

    }

    @IBAction func printBtnPressed(_ sender: Any) {

    }


}

extension PagesTableViewController: UITableViewDataSource {

    // MARK: - Table view data source

     func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return pages.count
    }

      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier: "PagesCell", for: indexPath)

     cell.textLabel?.text = pages[indexPath.row]

     return cell
     }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "DetailsViewSegue" {

        }
    }

}

DetailsViewController

import UIKit

class DetailsViewController: UIViewController {

    @IBOutlet weak var detailsTextField: UITextField!

    var childDelegate: basicChildInfo?

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func cancelBtnPressed(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }

    @IBAction func saveBtnPressed(_ sender: Any) {

        let data = detailsTextField.text
        childDelegate?.userEnteredChildInfo(data: data!)
        dismiss(animated: true, completion: nil)

    }
}

PrintViewController

import UIKit

class PrintViewController: UIViewController, basicChildInfo {

    @IBOutlet weak var printLabelOne: UILabel!


    override func viewDidLoad() {
        super.viewDidLoad()

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

    //protocol func pulled from child info -- Data from child info
    func userEnteredChildInfo(data: String) {
        printLabelOne.text = data
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "PrintSegue" {
            let childInfoVC: DetailsViewController = segue.destination as! DetailsViewController
            childInfoVC.childDelegate = self
        }
    }

    @IBAction func printBtnPressed(_ sender: Any) {

        print("Printing File")
        dismiss(animated: true, completion: nil)

    }

}

最后是我的协议。文件打开swift文件

import Foundation

protocol basicChildInfo {
    func userEnteredChildInfo(data: String)
}

1 个答案:

答案 0 :(得分:1)

我的猜测是DetailsViewController上的委托永远不会被设置。这是UI的控制流程序列(据我所知):

  1. 创建并展示了新的DetailsViewController
  2. 用户输入文字
  3. 用户点按“保存”按钮
  4. DetailsViewController通知其代表有关文本并自行解散,因此被删除
  5. 创建并展示了新的PrintViewController
  6. 因此,当DetailsViewController想要通知其代表有关输入的值时,该委托尚未设置;实际上PrintViewController此时甚至不存在。

    更糟糕的是,PrintViewController准备for segue中的代码很可能永远不会被调用,因为从打印VC到详细信息VC没有任何信号,并且此方法仅在segue-时运行基于过渡发生。

    所以,回到你要解决的问题:我建议你......

    • PagesTableViewController符合委托协议,并在出现DetailsViewController时将其设置为委托
    • 在委托回调中
    • ,将输入的数据存储在PagesTableViewController
    • 的成员变量中
    • 出现PrintViewController时,将该成员var中存储的值设置为PrintViewController
    • 的属性

    因此,这两项操作 - 在DetailsViewController上设置代理并在PrintViewController上配置输入的文字 - 进入PrintViewController的准备工作:

    class PagesTableViewController: UIViewController, BasicChildInfo {
      private var userText: String? = nil
    
      func userEnteredChildInfo(data: String) {
        userText.text = data
      }
    
      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          if segue.identifier == "DetailsViewSegue" {
            (segue.destination as! DetailsViewController).childDelegate = self
          }
          else if  segue.identifier == "PrintSegue" {
            (segue.destination as! PrintViewController).userText = self.userText
          }
      }