通过导航后退按钮传递数据
Pass data through navigation back button
我现在的情况是:
我正在使用 prepare for segue 将 4 个数组从 Progress Table 传递到 Detail Exercise,它工作正常!当我尝试将数据从 Detail Exercise Controller 传回 Progress Table Controller 时,问题就开始了。我想使用默认的导航后退按钮返回父视图。实际上我正在使用这段代码,但它不起作用,数据从子视图传递到父视图,但我在 Progress Table 中看不到结果,似乎我需要刷新,但我还在 viewDidLoad 之后尝试了 reloadData,但它不起作用。有什么建议吗?谢谢。
override func viewWillDisappear(animated : Bool) {
super.viewWillDisappear(animated)
if (self.isMovingFromParentViewController()){
print("n'drio")
let historyView = self.storyboard!.instantiateViewControllerWithIdentifier("historyView") as! HistoryTableViewController
historyView.isFirstTime = false
historyView.arrayData = arrayDataDetails
historyView.arrayRipetizioni = arrayRipetizioniDetails
historyView.arrayPeso = arrayPesoDetails
historyView.arrayRecupero = arrayRecuperoDetails
historyView.tableView.reloadData()
}
}
通常,协议和委托用于在屏幕之间来回传递数据。
// Define a delegate that is known to both view controllers
protocol DetailsExerciseDelegate {
func detailsWillDisappear(...);
}
class DetailsExerciseViewController {
// Accept the delegate as a property on the details view controller
var delegate : DetailsExerciseDelegate
override func viewWillDisappear(animated : Bool) {
super.viewWillDisappear(animated)
// When you want to send data back to the caller
// call the method on the delegate
if let delegate = self.delegate {
delegate.detailsWillDisappear(/* your data in one or more parameters */)
}
}
}
// Implement the delegate by adding the required function
class ProgressTableViewController: DetailsExerciseDelegate {
...
func detailsWillDisappear(...) {
// When the child calls the function, update the screen
historyView.isFirstTime = false
historyView.arrayData = arrayDataDetails
historyView.arrayRipetizioni = arrayRipetizioniDetails
historyView.arrayPeso = arrayPesoDetails
historyView.arrayRecupero = arrayRecuperoDetails
historyView.tableView.reloadData()
}
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if segue!.identifier == "DetailsExcercise" {
// And finally, when launching the child view,
// make sure to set the delegate.
let viewController = segue!.destinationViewController as DetailsExerciseViewController
viewController.delegate = self
}
}
}
话虽这么说,但似乎 non-standard 在单击后退按钮时试图保存数据。您确定不想在 "Done" 上执行此操作吗?
当您按下后退按钮时,导航控制器将调用 navigationController(willShowViewController:)
,因此您可以使用它来将数据传回您的初始视图控制器。示例如下:
使用UINavigationControllerDelegate
:
class DetailsViewController: UIViewController, UINavigationControllerDelegate {
// ^
var data: [String] = [] // Important!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
data = ["data has changed!"]
}
}
Swift 2:
extension DetailsViewController: UINavigationControllerDelegate {
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if let controller = viewController as? ProgressTableViewController {
controller.data = data // Here you pass the data back to your original view controller
}
}
}
Swift 3:
extension DetailsViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
(viewController as? ProgressTableViewController)?.data = data // Here you pass the to your original view controller
}
}
在此示例中,关键是使用 UINavigationControllerDelegate
并设置导航控制器的委托(在本例中为 self
)。完成此操作后,您可以使用后退按钮将数据发送回初始视图控制器。
就我个人而言,我更喜欢对我的数据使用 class:
为您的数据使用自定义 class:
class Data {
var array: [String] = []
}
进度视图控制器:
class ProgressTableViewController: UITableViewController {
var data = Data()
override func viewDidLoad() {
super.viewDidLoad()
data.array = ["some data"]
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.array.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = data.array[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "exerciseSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "exerciseSegue" {
let destination = segue.destinationViewController as! DetailsViewController
destination.data = data
}
}
}
详细视图控制器:
class DetailsViewController: UIViewController {
var data = Data()
override func viewDidLoad() {
super.viewDidLoad()
data.array = ["data has changed!"]
}
}
在最后一个示例中,您不必担心传递数据。每当您更改数据时,使用相同 class 的控制器也会有更改。
更简单的解决方案,您可以使用 self.navigationController?.viewControllers 访问以前的视图控制器,如下所示:
let vcsCount = self.navigationController?.viewControllers.count
self.navigationController?.viewControllers[vcsCount! - 2].updateData
updateData 是要在上一个视图控制器中更新的数据成员
此外,您可以使用此扩展程序:
extension UINavigationController {
func viewController<T: UIViewController>(class: T.Type) -> T? {
return viewControllers.filter({[=10=] is T}).first as? T
}
}
//
if let controller = navigationController?.viewController(class: MainViewController.self) {
controller.data = data
}
navigationController?.popViewController(animated: true)
我现在的情况是:
我正在使用 prepare for segue 将 4 个数组从 Progress Table 传递到 Detail Exercise,它工作正常!当我尝试将数据从 Detail Exercise Controller 传回 Progress Table Controller 时,问题就开始了。我想使用默认的导航后退按钮返回父视图。实际上我正在使用这段代码,但它不起作用,数据从子视图传递到父视图,但我在 Progress Table 中看不到结果,似乎我需要刷新,但我还在 viewDidLoad 之后尝试了 reloadData,但它不起作用。有什么建议吗?谢谢。
override func viewWillDisappear(animated : Bool) {
super.viewWillDisappear(animated)
if (self.isMovingFromParentViewController()){
print("n'drio")
let historyView = self.storyboard!.instantiateViewControllerWithIdentifier("historyView") as! HistoryTableViewController
historyView.isFirstTime = false
historyView.arrayData = arrayDataDetails
historyView.arrayRipetizioni = arrayRipetizioniDetails
historyView.arrayPeso = arrayPesoDetails
historyView.arrayRecupero = arrayRecuperoDetails
historyView.tableView.reloadData()
}
}
通常,协议和委托用于在屏幕之间来回传递数据。
// Define a delegate that is known to both view controllers
protocol DetailsExerciseDelegate {
func detailsWillDisappear(...);
}
class DetailsExerciseViewController {
// Accept the delegate as a property on the details view controller
var delegate : DetailsExerciseDelegate
override func viewWillDisappear(animated : Bool) {
super.viewWillDisappear(animated)
// When you want to send data back to the caller
// call the method on the delegate
if let delegate = self.delegate {
delegate.detailsWillDisappear(/* your data in one or more parameters */)
}
}
}
// Implement the delegate by adding the required function
class ProgressTableViewController: DetailsExerciseDelegate {
...
func detailsWillDisappear(...) {
// When the child calls the function, update the screen
historyView.isFirstTime = false
historyView.arrayData = arrayDataDetails
historyView.arrayRipetizioni = arrayRipetizioniDetails
historyView.arrayPeso = arrayPesoDetails
historyView.arrayRecupero = arrayRecuperoDetails
historyView.tableView.reloadData()
}
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if segue!.identifier == "DetailsExcercise" {
// And finally, when launching the child view,
// make sure to set the delegate.
let viewController = segue!.destinationViewController as DetailsExerciseViewController
viewController.delegate = self
}
}
}
话虽这么说,但似乎 non-standard 在单击后退按钮时试图保存数据。您确定不想在 "Done" 上执行此操作吗?
当您按下后退按钮时,导航控制器将调用 navigationController(willShowViewController:)
,因此您可以使用它来将数据传回您的初始视图控制器。示例如下:
使用UINavigationControllerDelegate
:
class DetailsViewController: UIViewController, UINavigationControllerDelegate {
// ^
var data: [String] = [] // Important!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
data = ["data has changed!"]
}
}
Swift 2:
extension DetailsViewController: UINavigationControllerDelegate {
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if let controller = viewController as? ProgressTableViewController {
controller.data = data // Here you pass the data back to your original view controller
}
}
}
Swift 3:
extension DetailsViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
(viewController as? ProgressTableViewController)?.data = data // Here you pass the to your original view controller
}
}
在此示例中,关键是使用 UINavigationControllerDelegate
并设置导航控制器的委托(在本例中为 self
)。完成此操作后,您可以使用后退按钮将数据发送回初始视图控制器。
就我个人而言,我更喜欢对我的数据使用 class:
为您的数据使用自定义 class:
class Data {
var array: [String] = []
}
进度视图控制器:
class ProgressTableViewController: UITableViewController {
var data = Data()
override func viewDidLoad() {
super.viewDidLoad()
data.array = ["some data"]
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.array.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = data.array[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "exerciseSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "exerciseSegue" {
let destination = segue.destinationViewController as! DetailsViewController
destination.data = data
}
}
}
详细视图控制器:
class DetailsViewController: UIViewController {
var data = Data()
override func viewDidLoad() {
super.viewDidLoad()
data.array = ["data has changed!"]
}
}
在最后一个示例中,您不必担心传递数据。每当您更改数据时,使用相同 class 的控制器也会有更改。
更简单的解决方案,您可以使用 self.navigationController?.viewControllers 访问以前的视图控制器,如下所示:
let vcsCount = self.navigationController?.viewControllers.count
self.navigationController?.viewControllers[vcsCount! - 2].updateData
updateData 是要在上一个视图控制器中更新的数据成员
此外,您可以使用此扩展程序:
extension UINavigationController {
func viewController<T: UIViewController>(class: T.Type) -> T? {
return viewControllers.filter({[=10=] is T}).first as? T
}
}
//
if let controller = navigationController?.viewController(class: MainViewController.self) {
controller.data = data
}
navigationController?.popViewController(animated: true)