ViewController 将 Swift 从一个 VC 推到另一个 VC 并返回
ViewController Pushing Swift From One VC to Another VC And Returning back
考虑两个视图控制器 Controller1
和 Controller2
,我在控制器 1 中创建了许多 UITextField
的形式,因为当用户单击特定的 UITextField
它移动到 Controller2,他在那里选择数据。
选择 Controller2
中的数据后,它会自动移动到 Controller1
,同时从 controller2 返回到 controller1,其他 UITextfield
数据被清除,仅找到来自 controller2 的选定数据。选择后,我需要在 UITextfield
中找到所有数据。
这是从Controller2
返回到Controller1
的代码
if(Constants.SelectedComplexName != nil)
{
let storyBoard: UIStoryboard = UIStoryboard(name: "NewUserLogin", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "NewUser") as! NewUserRegistrationViewController
self.present(newViewController, animated: true, completion: nil)
}
push your view controller instead of a present like this
if(Constants.SelectedComplexName != nil)
{
let storyBoard: UIStoryboard = UIStoryboard(name: "NewUserLogin", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "NewUser") as! NewUserRegistrationViewController
self.navigationController?.pushViewController(newViewController, animated: true)
}
然后像这样从 vc2 中选择数据后弹出
self.navigationController?.popViewController(animated: true)
如果您不使用导航控制器,那么您可以简单地调用 Dismiss
方法
self.dismiss(animated: true) {
print("updaae your data")
}
要传递消息,您需要实施 Delegate
。
protocol SecondViewControllerDelegate: NSObjectProtocol {
func didUpdateData(controller: SecondViewController, data: YourDataModel)
}
//This is your Data Model and suppose it contain 'name', 'email', 'phoneNumber'
class YourDataModel: NSObject {
var name: String? //
var phoneNumber: String?
var email: String?
}
class FirstViewController: UIViewController, SecondViewControllerDelegate {
var data: YourDataModel?
var nameTextField: UITextField?
var phoneNumberTextField: UITextField?
var emailTextField: UITextField?
override func viewDidLoad() {
super.viewDidLoad()
callWebApi()
}
func callWebApi() {
//After Success Fully Getting Data From Api
//Set this data to your global object and then call setDataToTextField()
//self.data = apiResponseData
self.setDataToTextField()
}
func setDataToTextField() {
self.nameTextField?.text = data?.name
self.phoneNumberTextField?.text = data?.phoneNumber
self.emailTextField?.text = data?.email
}
func openNextScreen() {
let vc2 = SecondViewController()//Or initialize it from storyboard.instantiate method
vc2.delegate = self//tell second vc to call didUpdateData of this class.
self.navigationController?.pushViewController(vc2, animated: true)
}
//This didUpdateData method will call automatically from second view controller when the data is change
func didUpdateData(controller: SecondViewController, data: YourDataModel) {
}
}
class SecondViewController: UIViewController {
var delegate: SecondViewControllerDelegate?
func setThisData(d: YourDataModel) {
self.navigationController?.popViewController(animated: true)
//Right After Going Back tell your previous screen that data is updated.
//To do this you need to call didUpdate method from the delegate object.
if let del = self.delegate {
del.didUpdateData(controller: self, data: d)
}
}
}
有几种方法可以做到,但这通常取决于您如何从 VC#1 移动到 VC#2 然后返回。
(1) 您发布的代码暗示您有一个包含两个视图控制器的故事板。在这种情况下,创建一个从 VC#1 到 VC#2 的转场,然后再返回一个 "unwind" 转场。两者都很容易做到。评论中提供的 很好地向您展示了,但是,取决于 (1) 您希望将多少数据传回 VC#1 和 (2) 如果您希望执行VC#2 上的一个函数,你也可以这样做:
VC#1:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowVC2" {
if let vc = segue.destination as? VC2ViewController {
vc.VC1 = self
}
}
}
VC#2:
weak var VC1:VC1ViewController!
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isMovingFromParentViewController {
VC1.executeSomeFunction()
}
}
基本上,您传递的是 VC1 的 整个 实例,因此可以访问未标记为 private
.[=17= 的所有内容]
(2) 如果您是来自 VC#1 的 presenting/dismissing VC#2,请使用答案之一所述的 delegate
样式。
VC#1:
var VC2 = VC2ViewController()
extension VC1ViewController: VC2ControlllerDelegate {
func showVC2() {
VC2.delegate = self
VC2.someData = someData
present(VC2, animated: true, completion: nil)
}
function somethingChanged(sender: VC2ViewController) {
// you'll find your data in sender.someData, do what you need
}
}
VC#2:
protocol VC2Delegate {
func somethingChanged(sender: VC2ViewController) {
delegate.somethingChanged(sender: self)
}
}
class DefineViewController: UIViewController {
var delegate:DefineVCDelegate! = nil
var someData:Any!
func dismissMe() {
delegate.somethingChanged(sender: self)
dismiss(animated: true, completion: nil)
}
}
}
基本上,您让 VC#1 成为 VC2 的代表。我更喜欢在 VC#2 中为 `delegate 声明语法,因为如果您忘记将 VC#1 设置为 VC#2 的委托,您的测试将在运行时强制出错.
考虑两个视图控制器 Controller1
和 Controller2
,我在控制器 1 中创建了许多 UITextField
的形式,因为当用户单击特定的 UITextField
它移动到 Controller2,他在那里选择数据。
选择 Controller2
中的数据后,它会自动移动到 Controller1
,同时从 controller2 返回到 controller1,其他 UITextfield
数据被清除,仅找到来自 controller2 的选定数据。选择后,我需要在 UITextfield
中找到所有数据。
这是从Controller2
返回到Controller1
if(Constants.SelectedComplexName != nil)
{
let storyBoard: UIStoryboard = UIStoryboard(name: "NewUserLogin", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "NewUser") as! NewUserRegistrationViewController
self.present(newViewController, animated: true, completion: nil)
}
push your view controller instead of a present like this
if(Constants.SelectedComplexName != nil)
{
let storyBoard: UIStoryboard = UIStoryboard(name: "NewUserLogin", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "NewUser") as! NewUserRegistrationViewController
self.navigationController?.pushViewController(newViewController, animated: true)
}
然后像这样从 vc2 中选择数据后弹出
self.navigationController?.popViewController(animated: true)
如果您不使用导航控制器,那么您可以简单地调用 Dismiss
方法
self.dismiss(animated: true) {
print("updaae your data")
}
要传递消息,您需要实施 Delegate
。
protocol SecondViewControllerDelegate: NSObjectProtocol {
func didUpdateData(controller: SecondViewController, data: YourDataModel)
}
//This is your Data Model and suppose it contain 'name', 'email', 'phoneNumber'
class YourDataModel: NSObject {
var name: String? //
var phoneNumber: String?
var email: String?
}
class FirstViewController: UIViewController, SecondViewControllerDelegate {
var data: YourDataModel?
var nameTextField: UITextField?
var phoneNumberTextField: UITextField?
var emailTextField: UITextField?
override func viewDidLoad() {
super.viewDidLoad()
callWebApi()
}
func callWebApi() {
//After Success Fully Getting Data From Api
//Set this data to your global object and then call setDataToTextField()
//self.data = apiResponseData
self.setDataToTextField()
}
func setDataToTextField() {
self.nameTextField?.text = data?.name
self.phoneNumberTextField?.text = data?.phoneNumber
self.emailTextField?.text = data?.email
}
func openNextScreen() {
let vc2 = SecondViewController()//Or initialize it from storyboard.instantiate method
vc2.delegate = self//tell second vc to call didUpdateData of this class.
self.navigationController?.pushViewController(vc2, animated: true)
}
//This didUpdateData method will call automatically from second view controller when the data is change
func didUpdateData(controller: SecondViewController, data: YourDataModel) {
}
}
class SecondViewController: UIViewController {
var delegate: SecondViewControllerDelegate?
func setThisData(d: YourDataModel) {
self.navigationController?.popViewController(animated: true)
//Right After Going Back tell your previous screen that data is updated.
//To do this you need to call didUpdate method from the delegate object.
if let del = self.delegate {
del.didUpdateData(controller: self, data: d)
}
}
}
有几种方法可以做到,但这通常取决于您如何从 VC#1 移动到 VC#2 然后返回。
(1) 您发布的代码暗示您有一个包含两个视图控制器的故事板。在这种情况下,创建一个从 VC#1 到 VC#2 的转场,然后再返回一个 "unwind" 转场。两者都很容易做到。评论中提供的
VC#1:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowVC2" {
if let vc = segue.destination as? VC2ViewController {
vc.VC1 = self
}
}
}
VC#2:
weak var VC1:VC1ViewController!
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isMovingFromParentViewController {
VC1.executeSomeFunction()
}
}
基本上,您传递的是 VC1 的 整个 实例,因此可以访问未标记为 private
.[=17= 的所有内容]
(2) 如果您是来自 VC#1 的 presenting/dismissing VC#2,请使用答案之一所述的 delegate
样式。
VC#1:
var VC2 = VC2ViewController()
extension VC1ViewController: VC2ControlllerDelegate {
func showVC2() {
VC2.delegate = self
VC2.someData = someData
present(VC2, animated: true, completion: nil)
}
function somethingChanged(sender: VC2ViewController) {
// you'll find your data in sender.someData, do what you need
}
}
VC#2:
protocol VC2Delegate {
func somethingChanged(sender: VC2ViewController) {
delegate.somethingChanged(sender: self)
}
}
class DefineViewController: UIViewController {
var delegate:DefineVCDelegate! = nil
var someData:Any!
func dismissMe() {
delegate.somethingChanged(sender: self)
dismiss(animated: true, completion: nil)
}
}
}
基本上,您让 VC#1 成为 VC2 的代表。我更喜欢在 VC#2 中为 `delegate 声明语法,因为如果您忘记将 VC#1 设置为 VC#2 的委托,您的测试将在运行时强制出错.