我在网上搜索了几个小时,现在觉得这是一项容易的任务,但事情并没有按计划进行。这个问题是编辑,一些伟大的家伙给出了伟大的答案,但我仍然在挣扎。
这是一个场景,我有一个始终可见的viewControllerA。这个视图的顶部有一个小按钮,当我单击它时,viewControllerB作为一个静态tableViewController出现。与其他应用程序一样,这是一个从左到右的幻灯片视图。
在tableView中有一个部分和几行,当我点击第四行显示viewControllerC时,那里有一个ui开关按钮。当我关闭viewControllerC时,viewControllerA再次出现。viewControllerB是我的菜单控制器,因此它不是我更关心的问题。现在我想把数据从viewControllerC传递到viewControllerA。这是我的破密码:
对于viewControllerC:

class viewControllerC: UIViewController {
 ..//
 @IBAction func switchTapped(_ sender: UISwitch) {
     let vc = viewControllerA()
     if sender.isOn == true {
         vc.state = true
     } else if sender.isOn == false {
         vc.state = false
     }
  }
 ..//
}

对于viewControllerA:
class viewControllerA: UIViewController, GMSMapViewDelegate {
  var state:Bool?
  ...//
  if self.state == true {
      self.mapView.isTrafficEnabled = true
    } else {
      self.mapView.isTrafficEnabled = false
   }
}

但这不起作用,我知道我没有朝着正确的方向前进从示例中可以看到,当UISwitch处于打开状态时,我要发送ture;当UISwitch从viewControllerC关闭时,我要发送false到viewControllerA。有些人建议使用委托方法,但我仍在努力。我在关注这个link,我认为“通过应用程序的共享状态向后传递数据”部分符合我的标准。尽管我需要帮助。提前谢谢。

最佳答案

首先,当您启动viewControllerA时:
让vc=viewControllerA()
您正在创建不引用第一个视图控件的viewcontrol的新实例。
可以用不同的方式将数据传递给viewcontrollers。
您可以使用delage模式,也可以使用unwind。
在delegate方法中,首先定义一个类类型协议,其中包含用于在viewControllerA中更改某些内容的函数定义。

protocol ViewControllerBDelegate: class {
    func changeSwitch(toValue: Boolean)
}

然后在ViewControllerB中定义一个弱引用来委托
weak var delegate: ViewControllerBDelegate?

然后在ViewControlA上采用这个协议:
extension ViewControllerA: ViewControllerBDelegate {
    func changeSwitch(toValue: Boolean) {
         state = toValue
     }
}

当您想要呈现或推送到ViewControllerB时,您应该将这个变量设置为self
let vc = ViewControllerB()
vc.delegate = self
present(vc, animated: true, completion: nil)
// or navigationController. pushViewController(vc, animated: true)

如果使用segue从一个viewcontroller导航到另一个viewcontroller,则应在prepare(对于segue,sender)中设置delegate变量。在ViewControllerA中重写此函数
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "mySegue" ,
       let vc = segue.destination as? ViewControllerB {
        vc.delegate = self
    }
}

然后,当开关值更改时,可以使用委托在ViewControllerA中更改值
delegate?.changeSwitch(toValue: sender.isOn)

在wind上,您可以将子视图控制器弹出或关闭到某个父视图,然后执行某些操作。您可以阅读完整的教程here
编辑
对于链委托,可以将一个委托传递给ViewController B,然后将同一个委托传递给ViewController C。
在视图控制器C中,定义同一类型的委托
weak var delegate: ViewControllerBDelegate?

然后在视图控制器B中,当您导航到视图控制器c时,您将传递相同的委托
let vc = ViewControllerC()
vc.delegate = self.delegate
present(vc, animated: true, completion: nil)

编辑2
SWRevealViewController是不同的场景。RevelController有一个名为frontViewController的属性。如果你不在“显示”上按任何其他控制器,它可能是你的ViewControllerA。用frontViewController处理它是很棘手的,你应该确定frontController是否是ViewControllerA。
所以我建议您使用另一种方法来与ViewControllerA通信。您可以使用通知中心。
extension Notification.Name {
    static let updateMap = Notification.Name("updateMap")
}

在ViewControllerA中
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(updateMap(_:)), name: .updateMap, object: nil )
}

@objc func updateMap(notification: NSNotification) {
  if let state = notification.userInfo?["state"] as? Bool {
      // do something with state
  }
}

在ViewControllerC中,当开关值更改时,您将发布一个通知:
let userInfoDic:[String: Bool] = ["state": sender.isOn]
  // post a notification
  NotificationCenter.default.post(name: .updateMap, object: nil, userInfo: userInfoDic)

如果显示中的frontViewController被再次按下。显示将启动
为frontViewController新建ViewControllerA。在这种情况下
要在UserDefault和ViewControllerA中设置,请阅读以下内容
设置。
使用用户默认值:
在ViewControllerC中
UserDefaults.standard.setValue(sender.isOn, forKey: "mapState")

在ViewControllerA中
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let state = UserDefaults.standard.value(forKey: "mapState") ?? false
    self.mapView.isTrafficEnabled = state
}

关于ios - 发现难以将数据传递到单独的viewController,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47271711/

10-10 01:00