Je suis dans cette situation:
Je passe 4 tableaux de la table de progression à l’exercice de détail en utilisant prepare for segue et cela fonctionne bien! Le problème commence lorsque j'essaie de transmettre les données du contrôleur d'exercice détaillé au contrôleur de table de progression. J'aimerais utiliser le bouton de navigation par défaut pour revenir à la vue parent. En fait, j'utilise ce code mais cela ne fonctionne pas, ainsi les données passent de la vue enfant à la vue parent mais je ne peux pas voir le résultat dans la table de progression. après le viewDidLoad et cela ne fonctionne pas. Toute suggestion? Je vous remercie.
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()
}
}
Lorsque vous appuyez sur le bouton Précédent, le contrôleur de navigation appelle navigationController(willShowViewController:)
afin que vous puissiez l'utiliser pour transmettre les données à votre contrôleur de vue initial. Un exemple est présenté ci-dessous:
Utilisation de 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
}
}
Dans cet exemple, la clé utilise UINavigationControllerDelegate
et définit le délégué du contrôleur de navigation (dans ce cas, c'est self
). Ceci fait, vous pouvez renvoyer les données à votre contrôleur de vue initial avec le bouton Précédent.
Personnellement, je préfère utiliser une classe pour mes données:
Utilisation d'une classe personnalisée pour vos données:
class Data {
var array: [String] = []
}
Contrôleur de vue de progression:
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
}
}
}
Contrôleur de vue de détails:
class DetailsViewController: UIViewController {
var data = Data()
override func viewDidLoad() {
super.viewDidLoad()
data.array = ["data has changed!"]
}
}
Dans le dernier exemple, vous n'avez pas à vous soucier de la transmission de données. Chaque fois que vous modifiez les données, les contrôleurs utilisant la même classe auront également les modifications.
En règle générale, les protocoles et les délégués sont utilisés pour échanger des données entre les écrans.
// 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
}
}
}
Cela étant dit, il semble inhabituel d'essayer de sauvegarder les données en cliquant sur le bouton Précédent. Êtes-vous sûr de ne pas vouloir faire cela sur "Terminé"?
Solution plus simple, vous pouvez utiliser self.navigationController? .ViewControllers pour accéder au contrôleur de vue précédent comme suit:
let vcsCount = self.navigationController?.viewControllers.count
self.navigationController?.viewControllers[vcsCount! - 2].updateData
updateData est le membre de données à mettre à jour sur le contrôleur de vue précédent
En outre, vous pouvez utiliser cette extension:
extension UINavigationController {
func viewController<T: UIViewController>(class: T.Type) -> T? {
return viewControllers.filter({$0 is T}).first as? T
}
}
//
if let controller = navigationController?.viewController(class: MainViewController.self) {
controller.data = data
}
navigationController?.popViewController(animated: true)