【问题标题】:Is there an alternative to ViewDidLoad? Any other place to write code which needs to be activated, when a viewController loads?有没有 ViewDidLoad 的替代品?当 viewController 加载时,还有其他地方可以编写需要激活的代码吗?
【发布时间】:2018-10-10 08:28:42
【问题描述】:

我有一个viewController,它包含三个文本字段。每个文本字段都连接到一个标签并使用NSUser Default,因此当用户在文本字段中写入内容时,文本会用一个键保存 - 并显示在分配给它的标签中。这很好用。

三个文本字段中的两个是供用户写“一个问题”和一个“额外标识符”的。如果用户不知道在这些中写什么,在屏幕顶部有两个按钮通向两个不同的tableViewControllers - 这两个按钮都包含用户可以选择的带有灵感/选项的 tableViews。我从每个中实现了一个 segue,因此当用户点击 tableViewCell 时,此单元格中的文本将传递到 viewController1 中的右侧文本字段 - 用户现在可以按保存并将此文本保存在 NSUser Default并让它显示在指定的标签中。

问题是这些 segues 当然是使用 ViewDidLoad 来显示从灵感 tableViews 传递的文本。这意味着,当您在保存您从第一个选择的“问题”后进入第二个 tableViewController 时,然后 - 由于 viewDidLoad 方法 - 所有文本字段和标签都被再次清除,并且只显示您刚刚传入的内容...所以:

我可以使用 viewDidLoad 以外的其他方法将数据传递到 ViewController1 吗?

或者我是否可以在 viewDidLoad 方法中添加一些代码,以便在您每次输入 viewController 时停止“重置”所有标签和文本字段?

或者我需要以完全不同的方式去做吗?

我希望这一切都有意义 - 对冗长的解释感到抱歉! :D

下面是 viewController1 的相关代码:

var chosenQuestion:String = ""
var chosenIdentifier:String = ""

override func viewDidLoad() {
    super.viewDidLoad()
DiaryQuestionTextField.text = chosenQuestion
RandomIdentifierTextField.text = chosenIdentifier
}


@IBAction func WriteDiaryName() {

    let title = "You have now chosen you diary's name. \n \n Do you wish to save this name and continue? \n \n You can always change all the details."
    let alert =  UIAlertController(title: title, message: nil, preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))

    alert.addAction(UIAlertAction(title: "Save", style: .default, handler: { action in
        self.defaults.setValue(self.DiaryNameTextField.text, forKey: "DiaryNameKey")
        let NewDiaryName = self.defaults.string(forKey: "DiaryNameKey")
        self.DiaryNameLabel.text = NewDiaryName

    }))
        present(alert, animated: true, completion: nil)
    }

“WriteQuestion”和“WriteExtraIdentifier”当然有两种类似的方法。

这是来自两个tableViewControllers之一的相关代码,带有“灵感”:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.destination is UpdatingIdentifiers {
        let vc = segue.destination as? UpdatingIdentifiers
        let selectedRowIndex = self.tableView.indexPathForSelectedRow
        let cell = self.tableView.cellForRow(at: selectedRowIndex!)
        let label = cell?.viewWithTag(420) as! UILabel
        vc?.chosenQuestion = label.text!
    }
}

谢谢!

【问题讨论】:

  • "一张图抵一千字" 可以给你的故事板加截图吗?
  • Swift 提示:所有 Swift 变量和函数名称都应该是 lowerCamelCase - 你的是 UpperCamelCase,这使得它们很难从类名中分辨出来
  • 我认为ViewWillAppear()ViewDidAppear()ViewControllerViewDidLoad() 的最佳替代品。
  • 我在问题的底部添加了两张我的故事板的照片。但是您认为对于这个问题,viewDidLoad 和 viedDidAppear 会有什么不同吗?我的意思是问题是每次给定方法运行时,“问题文本字段”和“标识符文本字段”都会更新。这意味着其中一个结果是空的,一个更新了..
  • 我唯一能想到的就是尝试实现某种 if-sentence,它说:如果文本字段为空,那么您应该使用新信息更新它 - 如果其他情况:保留信息,就是在里面!但我不知道如何制定它......你明白吗?

标签: ios swift uitableview segue nsuserdefaults


【解决方案1】:

对于这种情况,您可以简单地使用 closure 方法。

  1. ViewController2 中创建一个closure 变量。
  2. 每当您从ViewController1 呈现ViewController2 时,设置此closure 的值。
  3. 每当您在tableView 中选择ViewController2 中的一行并在closure 中传递所选值时,都调用closure
  4. 每当您从closure 获得新值时更新chosenQuestion,然后使用property observer 更新textField's 值。

示例代码:

class ViewController1: UIViewController
{
    @IBOutlet weak var DiaryQuestionTextField: UITextField!

    var chosenQuestion = "" {
        didSet{
            //Textfield will be updated everytime a new value is set in chosenQuestion variable
            self.DiaryQuestionTextField.text = self.chosenQuestion
        }
    }

    @IBAction func showInspirationVC(_ sender: UIButton)
    {
        let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
        controller.handler = {[weak self](data) in
            self?.chosenQuestion = data
        }
        self.present(controller, animated: true, completion: nil)
    }
}

class ViewController2: UIViewController, UITableViewDelegate, UITableViewDataSource
{
    var handler: ((String)->())?
    var data = ["Question-1", "Question-2", "Question-3", "Question-4", "Question-5"]

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return self.data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = self.data[indexPath.row]
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        self.dismiss(animated: true) {
            self.handler?(self.data[indexPath.row])
        }
    }
}

故事板:

先尝试实现一个简单的用例。而且您不需要在这种方法中使用 segues,因为您是以编程方式呈现控制器。

如果有任何问题,请告诉我。

【讨论】:

  • 我实现了这些 - 但它给了我错误:线程 1:致命错误:在此行上展开可选值时意外发现 nil:self.DiaryQuestionTextField.text = self.chosenQuestion
  • @AntonBjerg 什么?请详细说明。
  • 另外,是否有一个原因,在该示例中,您将 tableViewController 作为“UIViewController”和“UITableViewDelegate”。因为现在我的两个 tableViewControllers 都只是“UITableViewController”。这对这件事有什么影响吗?
  • 不,它没有。您可以完全根据您的要求使用UIViewController + UITableViewUITableViewController。如果您的控制器只包含一个` UITableView, it's better to use UITableViewController. In this example, I just tried to explain the closure` 方法,您可以使用它来与 b/w 2 个控制器进行通信。
  • 在实现了你的这些新方法之后,当我在灵感 tableView 中选择一个单元格时,应用程序崩溃 - 然后在展开后给我关于找到 nil 的错误......我在上面写的 - 关于我在上面写的那一行。但是我不明白为什么这些更改应该将 selectedQuestion 变成 nil?
【解决方案2】:

很简单,您只需使用 viewDidLoad 中 UserDefaults 中的值重新初始化“chosenQuestion”和“chosenIdentifier”即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-27
    • 2017-03-08
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多