使用prepareForSegue稍后在app中将数据传递给ViewController

时间:2017-02-24 20:19:15

标签: ios swift xcode

我想知道,使用prepareForSegue传递数据时,您是否可以稍后在应用程序中将数据传递给View Controller?例如,在第一个ViewController上,我让用户输入他们的名字。直到最后,所以稍后会有一些观点,我是否需要显示他们的名字。有没有办法传递他们的名字,而不必立即去结束视图?

3 个答案:

答案 0 :(得分:2)

使用协调员。

将ViewControllers解耦非常容易:

  • 而不是使用segues为每个ViewController提供委托
  • 创建一个协调器对象(此对象知道您的屏幕流程,而不是您的屏幕)
  • 协调员创建ViewControllers(它可以使用UIStoryboard instantiateViewController(withIdentifier:),因此 ViewController A 不必知道 ViewController B 存在
  • 而不是致电performSegue,而只是致电您的代表并传递数据

优势

  • 简单易用
  • 轻松重新排序流程中的屏幕
  • 高度分离(更容易测试)
  • 非常适合A / B测试
  • 大量扩展(您可以拥有多个协调员,每个流程一个)

样品

假设你有3个VC,第一个要求你的名字,第二个用于你的年龄,第三个用于显示数据。 AgeViewController知道NameViewController知道存在是没有意义的,稍后您可能想要更改订单甚至合并它们。

名称视图控制器

protocol NameViewControllerDelegate: class {
    func didInput(name: String)
}

class NameViewController: UIViewController {
    weak var delegate: NameViewControllerDelegate?

    @IBOutlet var nameTextField: UITextField!
    //Unimportant stuff ommited

    @IBAction func submitName(sender: Any) {
        guard let name = nameTextField.text else {
            // Do something, it's up to you what
            return
        }

        delegate?.didInput(name: name)
    }
}

年龄视图控制器

protocol AgeViewControllerDelegate: class {
    func didInput(age: Int)
}

class AgeViewController: UIViewController {
    weak var delegate: AgeViewControllerDelegate?

    @IBOutlet var ageTextField: UITextField!
    //Unimportant stuff ommited

    @IBAction func submitAge(sender: Any) {
        guard let ageString = ageTextField.text,
              let age = Int(ageString) else {
                // Do something, it's up to you what
            return
        }

        delegate?.didInput(age: age)
    }
}

显示器视图控制器

class DisplayerViewController: UIViewController {
    var age: Int?
    var name: String?
}

协调员

class Coordinator {
    var age: Int?
    var name: String?

    var navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    fileprivate lazy var storyboard: UIStoryboard = {
        return UIStoryboard(name: "MyStoryboard", bundle: nil)
    }()

    //This works if you name your screns after their classes
    fileprivate func viewController<T: UIViewController>(withType type: T.Type) -> T {
        return storyboard.instantiateViewController(withIdentifier: String(describing: type(of: type))) as! T
    }

    func start() -> UIViewController {
        let viewController = self.viewController(withType: NameViewController.self)
        viewController.delegate = self

        navigationController.viewControllers = [viewController]

        return viewController
    }
}

协调员+名称视图控制器代表

extension Coordinator: NameViewControllerDelegate {
    func didInput(name: String){
        self.name = name

        let viewController = self.viewController(withType: AgeViewController.self)
        viewController.delegate = self

        navigationController.pushViewController(viewController, animated: true)
    }
}

协调员+年龄视图控制器代表

extension Coordinator: AgeViewControllerDelegate {
    func didInput(age: Int) {
        self.age = age

        let viewController = self.viewController(withType: DisplayerViewController.self)
        viewController.age = age
        viewController.name = name

        navigationController.pushViewController(viewController, animated: true)
    }
}

答案 1 :(得分:1)

不是真的。您可以通过查看项目来传递视图,但这不是一种正确的做事方式。

我建议你有一个静态管理器或这种东西来在你的应用程序中全局存储信息以便以后检索

答案 2 :(得分:-1)

所有解决方案都非常好。您也可以尝试以下型号

<强> 1。 DataModel类

1.1 Should be singleton class
1.2 Declare value

第1步:ViewCOntroller-one

1创建单例类的sharedinstance     1.1分配值

第3步:ViewController-two

1创建单例类的sharedinstance     1.1获取值