ViewController 将 Swift 从一个 VC 推送到另一个 VC 并返回

Posted

技术标签:

【中文标题】ViewController 将 Swift 从一个 VC 推送到另一个 VC 并返回【英文标题】:ViewController Pushing Swift From One VC to Another VC And Returning back 【发布时间】:2018-10-05 12:59:06 【问题描述】:

考虑两个视图控制器 Controller1Controller2,我在控制器 1 中创建了许多 UITextField 的表单,当用户单击特定的 UITextField 时,它会移动到 Controller2 并选择那里的数据.

选择Controller2中的数据后,它会自动移动到Controller1,而从控制器2返回控制器1时,其他UITextfield数据被清除,只找到控制器2中选择的数据。选择后我需要在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)
   

【问题讨论】:

添加您的 VC1 代码以及如何从 VC2 弹出到 VC1 @Anbu.karthik 我的 VC1 代码让 storyBoard: UIStoryboard = UIStoryboard(name: "NewUserLogin", bundle: nil) let newViewController = storyBoard.instantiateViewController(withIdentifier: "ComplexList") as! ComplexSearchViewController self.present(newViewController, animated: true, completion: nil) 您可能想要使用展开转场。请看***.com/questions/35313747/… 仅找到来自 controller2 的选定数据 - 您如何将数据从 controller2 获取到 controller1? 【参考方案1】:

要传递消息,您需要实现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)
        
    

【讨论】:

【参考方案2】:
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")

【讨论】:

这很好地解释了如何push/pop,但没有说明在VC2上输入的数据将如何返回到VC1中显示。【参考方案3】:

有几种方法可以做到这一点,但这通常取决于您如何从 VC#1 移动到 VC#2 并返回。

(1) 您发布的代码意味着您有一个带有两个视图控制器的故事板。在这种情况下,创建从 VC#1 到 VC#2 的转场和“展开”转场。两者都相当容易做到。 cmets 中提供的link 可以很好地向您展示,但是,取决于 (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 的所有内容。

(2) 如果您要从 VC#1 呈现/关闭 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 的委托,您的测试将在运行时强制出错。

【讨论】:

以上是关于ViewController 将 Swift 从一个 VC 推送到另一个 VC 并返回的主要内容,如果未能解决你的问题,请参考以下文章

swift3:如何将 xib 呈现给 viewcontroller

将 ViewController 缩小为圆形过渡 - swift

如何将计时器中的数据传递给新的 ViewController (Swift 3)

如何将值从 SceneDelegate 文件传输到 ViewController (Swift 5)

将图像转移到下一个 ViewController (Swift)

iOS 和 Swift:ViewController 类已定义,但何时将其创建为对象?