私はこの状況にあります:
私は準備テーブルを使用してProgress TableからDetail Exerciseに4つの配列を渡していますが、うまく機能します! Detail Exercise ControllerからProgress Table Controllerにデータを渡そうとすると、問題が始まります。デフォルトのナビゲーション戻るボタンを使用して、親ビューに戻りたいのですが。実際にはこのコードを使用していますが、機能しません。子から親ビューにデータが渡されますが、進行状況テーブルに結果が表示されません。更新する必要があるようですが、reloadDataも試しました。 viewDidLoadの後、それは動作しません。なにか提案を?ありがとうございました。
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()
}
}
戻るボタンを押すと、ナビゲーションコントローラが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 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!"]
}
}
最後の例では、データの受け渡しについて心配する必要はありません。データを変更すると、同じクラスを使用するコントローラーにも変更が反映されます。
通常、プロトコルとデリゲートは、画面間でデータをやり取りするために使用されます。
// 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
}
}
}
そうは言っても、「戻る」ボタンをクリックしたときにデータを保存しようとするのは標準的ではないようです。代わりに「完了」でこれを実行しないでよろしいですか?
次のように、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({$0 is T}).first as? T
}
}
//
if let controller = navigationController?.viewController(class: MainViewController.self) {
controller.data = data
}
navigationController?.popViewController(animated: true)