是否有 ViewDidLoad 的替代方案?当 viewController 加载时,还有其他地方可以编写需要激活的代码吗?
Is there an alternative to ViewDidLoad? Any other place to write code which needs to be activated, when a viewController loads?
我有一个 viewController
,其中包含三个文本字段。每个文本字段都连接到一个标签并使用 NSUser Default
以便当用户在文本字段中写入内容时,文本会使用一个键保存 - 并显示在分配给它的标签中。那很好用。
三个文本字段中的两个供用户编写 "a question" 和一个 "extra identifier"。如果用户不知道在其中写什么,在屏幕顶部有两个按钮指向两个不同的 tableViewControllers
- 两个按钮都包含用户可以选择的带有 inspiration/options 的 tableView .我从每个实现了一个 segue,这样当用户点击 tableViewCell
时,此单元格中的文本将传递到 viewController1
中的正确文本字段 - 用户现在可以按保存并将此文本保存在NSUser Default
并让它显示在分配的标签中。
问题是这些 segues 当然使用 ViewDidLoad 来显示从灵感 tableViews 传递的文本。这意味着当您在保存后输入第二个 tableViewController 时,您从第一个选择 "question" ,然后 - 由于 viewDidLoad
方法 - 所有文本字段和标签将再次清除,只有你刚刚通过的内容里面显示...所以:
我可以使用 viewDidLoad
之外的其他方法将数据传递到 ViewController1 吗?
或者我可以向 viewDidLoad 方法添加一些代码,以便它在您每次输入 viewController
时停止 "resetting" 所有标签和文本字段吗?
还是我需要换一种完全不同的方式?
我希望这一切都有意义 - 抱歉解释太长了! :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
和 "inspiration" 之一的相关代码:
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!
}
}
谢谢!
对于这种情况,您可以简单地使用 closure
方法。
- 在
ViewController2
中创建一个 closure
变量。
- 每当您从
ViewController1
显示 ViewController2
时设置此 closure
的值。
- 每当您 select 在
ViewController2
的 tableView
中的一行时调用 closure
并在 closure
中传递 selected 值.
- 每当您从
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,因为您是以编程方式呈现控制器的。
如有任何问题,请告诉我。
很简单,您只需要使用 viewDidLoad 中 UserDefaults 的值重新初始化 "chosenQuestion" 和 "chosenIdentifier" 就可以了。
我有一个 viewController
,其中包含三个文本字段。每个文本字段都连接到一个标签并使用 NSUser Default
以便当用户在文本字段中写入内容时,文本会使用一个键保存 - 并显示在分配给它的标签中。那很好用。
三个文本字段中的两个供用户编写 "a question" 和一个 "extra identifier"。如果用户不知道在其中写什么,在屏幕顶部有两个按钮指向两个不同的 tableViewControllers
- 两个按钮都包含用户可以选择的带有 inspiration/options 的 tableView .我从每个实现了一个 segue,这样当用户点击 tableViewCell
时,此单元格中的文本将传递到 viewController1
中的正确文本字段 - 用户现在可以按保存并将此文本保存在NSUser Default
并让它显示在分配的标签中。
问题是这些 segues 当然使用 ViewDidLoad 来显示从灵感 tableViews 传递的文本。这意味着当您在保存后输入第二个 tableViewController 时,您从第一个选择 "question" ,然后 - 由于 viewDidLoad
方法 - 所有文本字段和标签将再次清除,只有你刚刚通过的内容里面显示...所以:
我可以使用 viewDidLoad
之外的其他方法将数据传递到 ViewController1 吗?
或者我可以向 viewDidLoad 方法添加一些代码,以便它在您每次输入 viewController
时停止 "resetting" 所有标签和文本字段吗?
还是我需要换一种完全不同的方式?
我希望这一切都有意义 - 抱歉解释太长了! :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
和 "inspiration" 之一的相关代码:
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!
}
}
谢谢!
对于这种情况,您可以简单地使用 closure
方法。
- 在
ViewController2
中创建一个closure
变量。 - 每当您从
ViewController1
显示ViewController2
时设置此closure
的值。 - 每当您 select 在
ViewController2
的tableView
中的一行时调用closure
并在closure
中传递 selected 值. - 每当您从
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,因为您是以编程方式呈现控制器的。
如有任何问题,请告诉我。
很简单,您只需要使用 viewDidLoad 中 UserDefaults 的值重新初始化 "chosenQuestion" 和 "chosenIdentifier" 就可以了。