Swift – 使用 popViewController 并将数据传递给您要返回的 ViewController
Swift – Using popViewController and passing data to the ViewController you're returning to
我的第一个视图控制器 ViewController
上有一个名为 showSettings
的可选 bool
变量,我从 SecondViewController
返回到 ViewController
.
在弹出之前,我想将 bool 设置为 true。实例化另一个视图控制器似乎是错误的,因为 ViewController
在内存中。
最好的方法是什么?如果这对您的回答很重要,我不会使用故事板。
感谢您的帮助
所以我想通了,主要是基于这个 post – http://makeapppie.com/2014/09/15/swift-swift-programmatic-navigation-view-controllers-in-swift/
在 SecondViewController
中,在 class 声明上方,添加此代码:
protocol SecondVCDelegate {
func didFinishSecondVC(controller: SecondViewController)
}
然后在SecondViewContoller
里面添加一个class变量:
var delegate: MeditationVCDelegate! = nil
然后在按钮指向的函数中添加:
self.navigationController?.popViewControllerAnimated(true)
delegate.didFinishSecondVC(self)
我们在这里做的是在 SecondViewController
中执行弹出操作,并且 不 传递任何数据,但是由于我们已经定义了协议,所以我们将在 ViewController
中使用它来处理数据。
所以接下来,在 ViewController
中,将您在 SecondViewController
中定义的协议添加到 class 列表中 ViewController
继承自:
class ViewController: UIViewController, SecondVCDelegate { ... your code... }
您需要添加我们在新协议中定义的函数,以使编译器满意。在 ViewController
的 class 中,添加:
func didFinishSecondVC(controller: SecondViewController) {
self.myBoolVar = true
controller.navigationController?.popViewControllerAnimated(true)
}
在我们调用 didFinishSecondVC
的 SecondViewController
中,我们在 ViewController
class 内部调用此方法,我们将弹出到控制器。这类似于我们在 SecondViewController
中编写此代码,但我们将其编写在 ViewController
中,并且我们使用委托来管理两者之间的消息传递。
最后,在 ViewController
中,在我们要将 push 推送到 SecondViewController
的函数中,添加以下代码:
let secondVC = secondViewController()
secondVC.delegate = self
self.navigationController?.pushViewController(secondVC, animated: true)
就是这样!您应该准备好在不使用故事板的情况下在两个视图控制器之间传递代码!
我在寻找解决方法时遇到了这个问题。由于我更频繁地使用故事板,我发现我可以在导航堆栈中获取控制器数组,获取位于顶部的当前控制器之前的那个,检查它是否是我的委托,如果是,则将其转换为委托,设置我的方法,然后将自己从堆栈中弹出。虽然代码在 ObjC 中,但它应该很容易翻译成 swift:
// we need to get the previous view controller
NSArray *array = self.navigationController.viewControllers;
if ( array.count > 1) {
UIViewController *controller = [array objectAtIndex:(array.count - 2)];
if ( [controller conformsToProtocol:@protocol(GenreSelectionDelegate)]) {
id<GenreSelectionDelegate> genreDelegate = (id<GenreSelectionDelegate>)controller;
[genreDelegate setGenre:_selectedGenre];
}
[self.navigationController popViewControllerAnimated:YES];
}
_ = self.navigationController?.popViewController(animated: true)
let previousViewController = self.navigationController?.viewControllers.last as! PreviousViewController
previousViewController.PropertyOrMethod
扩展 Abdul Baseer Khan 的回答:
对于当前视图控制器可能已被不同类型的先前视图控制器加载的情况,我们可以使用更安全的 as?
调用而不是 as!
,这将 return nil
如果控制器不是我们要找的:
let previousVC = self.navigationController?.viewControllers.last as? AnExampleController
previousVC?.doSomething()
不过,您需要为每个可以加载当前视图控制器的不同视图控制器重复该操作。
因此,您可能想要实现一个协议以分配给所有可能的先前视图控制器:
protocol PreviousController: UIViewController {
func doSomething()
}
class AnExampleController: UIViewController, PreviousController {
// ...
func doSomething() {}
}
class AnotherController: UIViewController, PreviousController {
// ...
func doSomething() {}
}
class CurrentController: UIViewController {
// ...
func goBack() {
let previousVC = self.navigationController?.viewControllers.last as? PreviousController
previousVC?.doSomething()
}
}
我的第一个视图控制器 ViewController
上有一个名为 showSettings
的可选 bool
变量,我从 SecondViewController
返回到 ViewController
.
在弹出之前,我想将 bool 设置为 true。实例化另一个视图控制器似乎是错误的,因为 ViewController
在内存中。
最好的方法是什么?如果这对您的回答很重要,我不会使用故事板。
感谢您的帮助
所以我想通了,主要是基于这个 post – http://makeapppie.com/2014/09/15/swift-swift-programmatic-navigation-view-controllers-in-swift/
在 SecondViewController
中,在 class 声明上方,添加此代码:
protocol SecondVCDelegate {
func didFinishSecondVC(controller: SecondViewController)
}
然后在SecondViewContoller
里面添加一个class变量:
var delegate: MeditationVCDelegate! = nil
然后在按钮指向的函数中添加:
self.navigationController?.popViewControllerAnimated(true)
delegate.didFinishSecondVC(self)
我们在这里做的是在 SecondViewController
中执行弹出操作,并且 不 传递任何数据,但是由于我们已经定义了协议,所以我们将在 ViewController
中使用它来处理数据。
所以接下来,在 ViewController
中,将您在 SecondViewController
中定义的协议添加到 class 列表中 ViewController
继承自:
class ViewController: UIViewController, SecondVCDelegate { ... your code... }
您需要添加我们在新协议中定义的函数,以使编译器满意。在 ViewController
的 class 中,添加:
func didFinishSecondVC(controller: SecondViewController) {
self.myBoolVar = true
controller.navigationController?.popViewControllerAnimated(true)
}
在我们调用 didFinishSecondVC
的 SecondViewController
中,我们在 ViewController
class 内部调用此方法,我们将弹出到控制器。这类似于我们在 SecondViewController
中编写此代码,但我们将其编写在 ViewController
中,并且我们使用委托来管理两者之间的消息传递。
最后,在 ViewController
中,在我们要将 push 推送到 SecondViewController
的函数中,添加以下代码:
let secondVC = secondViewController()
secondVC.delegate = self
self.navigationController?.pushViewController(secondVC, animated: true)
就是这样!您应该准备好在不使用故事板的情况下在两个视图控制器之间传递代码!
我在寻找解决方法时遇到了这个问题。由于我更频繁地使用故事板,我发现我可以在导航堆栈中获取控制器数组,获取位于顶部的当前控制器之前的那个,检查它是否是我的委托,如果是,则将其转换为委托,设置我的方法,然后将自己从堆栈中弹出。虽然代码在 ObjC 中,但它应该很容易翻译成 swift:
// we need to get the previous view controller
NSArray *array = self.navigationController.viewControllers;
if ( array.count > 1) {
UIViewController *controller = [array objectAtIndex:(array.count - 2)];
if ( [controller conformsToProtocol:@protocol(GenreSelectionDelegate)]) {
id<GenreSelectionDelegate> genreDelegate = (id<GenreSelectionDelegate>)controller;
[genreDelegate setGenre:_selectedGenre];
}
[self.navigationController popViewControllerAnimated:YES];
}
_ = self.navigationController?.popViewController(animated: true)
let previousViewController = self.navigationController?.viewControllers.last as! PreviousViewController
previousViewController.PropertyOrMethod
扩展 Abdul Baseer Khan 的回答:
对于当前视图控制器可能已被不同类型的先前视图控制器加载的情况,我们可以使用更安全的 as?
调用而不是 as!
,这将 return nil
如果控制器不是我们要找的:
let previousVC = self.navigationController?.viewControllers.last as? AnExampleController
previousVC?.doSomething()
不过,您需要为每个可以加载当前视图控制器的不同视图控制器重复该操作。
因此,您可能想要实现一个协议以分配给所有可能的先前视图控制器:
protocol PreviousController: UIViewController {
func doSomething()
}
class AnExampleController: UIViewController, PreviousController {
// ...
func doSomething() {}
}
class AnotherController: UIViewController, PreviousController {
// ...
func doSomething() {}
}
class CurrentController: UIViewController {
// ...
func goBack() {
let previousVC = self.navigationController?.viewControllers.last as? PreviousController
previousVC?.doSomething()
}
}