我在网上搜索了几个小时,现在觉得这是一项容易的任务,但事情并没有按计划进行。这个问题是编辑,一些伟大的家伙给出了伟大的答案,但我仍然在挣扎。
这是一个场景,我有一个始终可见的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/