在TableViewController和ViewController之间进行委托

时间:2018-09-12 13:50:38

标签: ios swift

在开发iOS的第一周,我就陷入了在视图控制器之间传递数据的问题。我的设置包括一个带有VC的视图(其中包含一个按钮)以及一个容器视图(没有关联的视图控制器)。容器视图具有使用TableViewController嵌入到TableView的嵌入式Segue。该表有6行,每行都有一个步进器,可以更改关联行上文本视图的值。我想做的是,当我按下主视图上的按钮时,收集所有文本视图的值。

我正在尝试使用委托来执行此操作,但是当我按下按钮时,返回的值始终为nil。我相信问题是与VC没有通过prepareForSegue函数传递给表视图控制器有关的,但是我不确定为什么吗?可能与控制器的加载顺序有关?

import UIKit

class PredictionViewController: UIViewController, PredictionDelegate {

    var predictionData: String!

    @IBOutlet weak var messageTextBox: UITextView!
    @IBOutlet weak var predictionSubmitButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        self.messageTextBox.isEditable = false
    }

    override func viewDidAppear(_ animated: Bool) {

    }

    func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
        if (segue.identifier == "predictionSegue") {
            // pass data to next view
            let vc = segue.destination as! PredictionsTableViewController
            vc.predictionHomeDelegate = self
        }
    }

    func receiveData(with data: String) {
        predictionData = data
        print(predictionData)
    }

    @IBAction func predictionSubmitButtonAction(_ sender: UIButton) {
        print(predictionData)
    }

}

TableViewController :(最小化)

import UIKit

protocol PredictionDelegate: class {
    func receiveData(with data: String)
}

class PredictionsTableViewController: UITableViewController, PredictionDelegate {

    weak var predictionHomeDelegate: PredictionDelegate?

    @IBOutlet weak var homeTeamScore1: UITextView!
    @IBOutlet weak var homeTeamStepper1: UIStepper!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    override func viewDidAppear(_ animated: Bool) {

    }

    func getPredictionList() {
        //does some stuff
        self.passDataBackwards()
    }

    func receiveData(with data: String) {}

    func passDataBackwards() {
        let data = "{\"score\":\"1\"}"
        predictionHomeDelegate?.receiveData(with: data)
    }

    @IBAction func homeTeamStepper1Action(_ sender: UIStepper) {

        let score = Int(sender.value).description
        homeTeamScore1.text = score
        self.passDataBackwards()
    }
}

storyboard view

感谢您的任何帮助!

3 个答案:

答案 0 :(得分:1)

编辑:

评论后...

您对协议和委托有错误的认识。这里不需要它们。

相反,在您的“家用” VC中,获得对嵌入式VC的引用。然后,在嵌入式VC中添加一个可以调用以获取其数据的函数。

Numpy documentation

// "home" view controller
class PredictionViewController: UIViewController {

    // this will be a reference to the embedded view controller
    var embeddedVC: PredictionsTableViewController?

    @IBAction func getDataButtonTapped(_ sender: Any) {
        if let tableData = embeddedVC?.getMyData() {
            print("Result: \(tableData)")
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "predictionSegue") {
            if let vc = segue.destination as? PredictionsTableViewController {
                // get a reference to the embedded VC
                self.embeddedVC = vc
            }
        }
    }

}

// embedded view controller
class PredictionsTableViewController: UIViewController {

    var numTaps = 0

    func getMyData() -> String {
        return "\(numTaps)"
    }

    @IBAction func didTap(_ sender: Any) {
        numTaps += 1
    }

}

您已经关闭,但是有一些错误...

这是一个非常非常简单的示例。带容器的视图控制器,其中包含带有按钮的视图控制器。

代码:

import UIKit

// your protocol    
protocol PredictionDelegate: class {
    func receiveData(with data: String)
}

// embedded view controller
// NOTE: this should NOT include PredictionDelegate
class PredictionsTableViewController: UIViewController {

    weak var predictionHomeDelegate: PredictionDelegate?

    @IBAction func didTap(_ sender: Any) {
        // on button tap, "send data back"
        predictionHomeDelegate?.receiveData(with: "Test")
    }

}

// "home" view controller
// NOTE: this DOES include PredictionDelegate
class PredictionViewController: UIViewController, PredictionDelegate {

    func receiveData(with data: String) {
        print(data)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "predictionSegue") {
            if let vc = segue.destination as? PredictionsTableViewController {
                // set self as the delegate of the embedded PredictionsTableViewController
                vc.predictionHomeDelegate = self
            }
        }
    }

}

注意:

  • 请勿在嵌入式视图控制器中包含func receiveData(with data: String) {}
  • 请勿将PredictionDelegate分配给嵌入式视图控制器

答案 1 :(得分:0)

您需要将segue绑定到vc本身而不是单元格上,并使用

self.performSegue(withIdentifier: "predictionSegue", sender: nil)

答案 2 :(得分:0)

由于这是两个单独的屏幕,所以我不太确定在第一个视图控制器上具有从第二个提交数据的按钮是否有意义,该按钮是否可以仅位于第二个屏幕上。如果由于某种原因不能通过在第一个视图控制器上添加公共变量,在第二个视图控制器上添加一个公共变量,然后在第二个视图控制器上添加另一个prepare方法,将数据传回第一个视图控制器,就像在添加委托。