Ios 通过导航返回按钮传递数据
我的处境是: 我正在使用prepare for segue将进度表中的4个数组传递给详细练习,效果很好!当我尝试将数据从详细练习控制器传回进度表控制器时,问题就开始了。我想使用默认的导航返回按钮返回到父视图。实际上,我正在使用这段代码,但它不起作用,数据从子视图传递到父视图,但我在进度表中看不到结果,似乎我需要刷新,但我还尝试在viewDidLoad之后重新加载数据,但它不起作用。有什么建议吗?多谢各位Ios 通过导航返回按钮传递数据,ios,swift,uinavigationcontroller,pass-data,Ios,Swift,Uinavigationcontroller,Pass Data,我的处境是: 我正在使用prepare for segue将进度表中的4个数组传递给详细练习,效果很好!当我尝试将数据从详细练习控制器传回进度表控制器时,问题就开始了。我想使用默认的导航返回按钮返回到父视图。实际上,我正在使用这段代码,但它不起作用,数据从子视图传递到父视图,但我在进度表中看不到结果,似乎我需要刷新,但我还尝试在viewDidLoad之后重新加载数据,但它不起作用。有什么建议吗?多谢各位 override func viewWillDisappear(animated : Bo
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
}
}
}
尽管如此,在单击“后退”按钮时尝试保存数据似乎是不标准的。您确定不想改为在“完成”时执行此操作吗?当您按下后退按钮时,导航控制器将调用
导航控制器(willShowViewController:)
,以便您可以使用此按钮将数据传递回初始视图控制器。示例如下所示:
使用UINavigationControllerDelegate
:
class DetailsViewController: UIViewController, UINavigationControllerDelegate {
// ^
var data: [String] = [] // Important!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
data = ["data has changed!"]
}
}
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
}
}
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!"]
}
}
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:
class DetailsViewController: UIViewController, UINavigationControllerDelegate {
// ^
var data: [String] = [] // Important!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
data = ["data has changed!"]
}
}
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
}
}
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!"]
}
}
在本例中,按键使用UINavigationControllerDelegate
并设置导航控制器的委托(在本例中为self
)。完成此操作后,可以使用“后退”按钮将数据发送回初始视图控制器
就我个人而言,我更喜欢使用类来处理我的数据:
为数据使用自定义类:
class DetailsViewController: UIViewController, UINavigationControllerDelegate {
// ^
var data: [String] = [] // Important!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
data = ["data has changed!"]
}
}
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
}
}
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 DetailsViewController: UIViewController, UINavigationControllerDelegate {
// ^
var data: [String] = [] // Important!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
data = ["data has changed!"]
}
}
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
}
}
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 DetailsViewController: UIViewController, UINavigationControllerDelegate {
// ^
var data: [String] = [] // Important!
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
data = ["data has changed!"]
}
}
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
}
}
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!"]
}
}
在上一个示例中,您不必担心数据的传递。每当您更改数据时,使用同一类的控制器也将进行更改。更简单的解决方案您可以使用self.navigationController?.viewControllers访问以前的视图控制器,如下所示:
let vcsCount = self.navigationController?.viewControllers.count
self.navigationController?.viewControllers[vcsCount! - 2].updateData
updateData是要在上一个view controller更新的数据成员。此外,您可以使用此扩展:
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)
扩展UINavigationController{
func viewController(类:T.Type)->T{
返回viewControllers.filter({$0是T})
}
}
//
如果let controller=navigationController?.viewController(类:MainViewController.self){
controller.data=数据
}
navigationController?.popViewController(动画:true)
感谢您回答我的问题,但您的代码根本无法理解!在
func detailswilldemouse
中,如何将数据传递回父视图??您在何处初始化historyView?请记住,您的类detailseerciseViewController
将有一个强大的引用循环,因为委托将阻止它被释放。使其弱
将解决这个问题。正如@Eendje在他的评论中所说的,您需要使用弱引用来实现委托,以避免任何错误cycle@Eendje对不起,我是新的协议和代表,请你回答我的问题与一些代码的例子来解决我的问题。非常感谢你!而不是传递它,你也可以考虑创建一个自定义类,将数组作为类属性,所以每当你在练习视图控制器中更改它们时,它们也会在进度视图控制器中改变。非常感谢你!今天学了一件新东西。非常感谢,伊恩杰:)为什么投反对票?我想知道,这样我可以纠正它。我喜欢第一个例子!在我从扩展中删除冗余的UINavigationControllerDelegate
后,第一个示例就成功了。