ios 如何在dismiss ViewController时将数据传递给另一个控制器?

5cnsuln7  于 2023-07-01  发布在  iOS
关注(0)|答案(5)|浏览(105)

我想通过我的数据从一个ViewController到另一个VC上VC dismiss。这可能吗?
我尝试了下一个方法,没有成功:
点击按钮时:

self.dismiss(animated: true) { 
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "EditViewController") as! EditViewController
        controller.segueArray = [values]
    }

EditViewController再次出现时,我的segueArray在那里是nil
我如何将数据从my ViewController传递到EditViewController

ttisahbt

ttisahbt1#

将数据传递回前一个视图控制器的最好方法是通过委托。。当从ViewController A转到B时,将视图控制器A作为委托传递,并在ViewController B的viewWillDisappear方法上,调用ViewController A中的委托方法。协议将帮助定义委托和需要由以前的VC实现的方法。这里有一个简单的例子:
传递数据的协议:

protocol isAbleToReceiveData {
  func pass(data: String)  //data: string is an example parameter
}

视图控制器A:

class viewControllerA: UIViewController, isAbleToReceiveData {

  func pass(data: String) { //conforms to protocol
  // implement your own implementation
   }

  prepare(for: Segue) {
    /** code for passing data **/
    let vc2 = ViewCOntrollerB()  /
    vc2.delegate = self   //sets the delegate in the new viewcontroller 
                          //before displaying
    present(vc2)
  }
}

正在解除viewcontroller:

class viewControllerB: UIViewController {

  var delegate: isAbleToReceiveData

  viewWillDisappear {
      delegate.pass(data: "someData") //call the func in the previous vc
  }
}
b09cbbtk

b09cbbtk2#

在解除完成块中,创建EditViewController的新示例。我假设导航堆栈中存在另一个EditViewController示例,您需要找到该示例并将segueArray设置为values。你可以通过遍历你的导航堆栈的viewcontrollers来实现,比如:

viewController.navigationController?.viewControllers.forEach({ (vc) in
    if let editVC = vc as? EditViewController {
        editVC.segueArray = ....
    }
})

但我建议使用delegate模式,比如:

protocol EditViewControllerDelegate: class {
    func setSegueArray(segues: [UIStoryboardSegue])
}

在dismiss块所在的viewcontroller(称之为ViewController)中,声明一个delegate属性:

class ViewController: UIViewController {
    weak var delegate: EditViewControllerDelegate?
    ....
}

然后,在呈现(我假设来自EditViewController)ViewController的示例时,设置委托如下:

...
if let vc = presentingViewController as? ViewController {
    vc.delegate = self
}

并使EditViewController符合委托协议,如:

extension EditViewController: EditViewControllerDelegate {
    func setSegueArray(segues: [UIStoryboardSegue]) {
        // Do the data setting here eg. self.segues = segues
    }
}
42fyovps

42fyovps3#

要检测何时按下视图控制器上的后退按钮,我只需用途:

override func didMove(toParentViewController parent: UIViewController?) {
    guard parent == nil else { return } // Back button pressed

    ... // Pass on the info as shown in you example
} // didMoveToParentViewController
von4xj4u

von4xj4u4#

通用解决方案:(🔸Swift 5.1)

/**
 * Returns a ViewController of a class Kind
 * ## Examples:
 * UIView.vc(vcKind: CustomViewController.self) // ref to an instance of CustomViewController
 */
public static func vc<T: UIViewController>(vcKind: T.Type? = nil) -> T? {
   guard let appDelegate = UIApplication.shared.delegate, let window = appDelegate.window else { return nil }
   if let vc = window?.rootViewController as? T {
      return vc
   } else if let vc = window?.rootViewController?.presentedViewController as? T {
      return vc
   } else if let vc = window?.rootViewController?.children {
      return vc.lazy.compactMap { $0 as? T }.first
   }
   return nil
}
rlcwz9us

rlcwz9us5#

我认为最简单的解决方案是使用完成处理程序:
示例:

class EditViewController {
    let secondController = SecondController()
    
    func showSecondController() {
        secondController.show() { data in
            //
        }
    }
}

class SecondController {
    var completion: ((_ data: Any?) -> Void)?
    
    func show(completion: @escaping (_ data: Any?) -> Void) {
        // Show something
        self.completion = completion
    }

    func dismiss() {
        if let completion = self.completion {
            completion(nil)
        }
    }
}

相关问题