发现很难将数据传递给单独的viewController

时间:2017-11-13 19:06:26

标签: ios swift

我已经在网上搜索了几个小时,现在认为这将是一件容易的事,但事情并没有按计划进行。这个问题经过编辑,一些伟大的家伙给出了很好的答案,但我仍然在苦苦挣扎。

这是一个场景,我有一个始终可见的 viewControllerA 。此视图顶部有一个小按钮,当我点击它时, viewControllerB 作为静态 tableViewController 。它是一个从左到右的幻灯片视图,说实话就像其他应用程序一样。

tableView中有一个部分和几个行,当我点击第四行时,我出现 viewControllerC ,那里有一个 UISwitch 按钮。当我关闭 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 false > off viewControllerC viewControllerA 。有些人提出了委托方法,但我仍在努力。我正在关注此link,我认为“通过应用程序的共享状态向后传递数据”部分符合我的标准。虽然我需要帮助。提前谢谢。

2 个答案:

答案 0 :(得分:4)

您可以使用Delegate模式传递数据,这是一个想法:

WHERE date d
   BETWEEN '2017-01-01'         -- just a sample fixed date
   AND DATEADD(D, CONTACT_DATE, -1) -- to show a day before Contact Date

答案 1 :(得分:1)

首先,当你启动viewControllerA:

  

让vc = viewControllerA()

您正在创建一个新的viewcontrol实例,它不会引用您的第一个视图控件。

您可以通过不同方式将数据传递给viewcontrollers。 您可以使用delage模式,也可以使用展开。

在委托方法中,首先定义一个类类型协议,其中包含一个函数定义,用于在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)。在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)

on wind允许您将子视图控制器弹出或关闭到某个父级,然后执行某些操作。您可以阅读完整的教程here

修改

对于链委托,您可以将委托传递给ViewController B,然后将相同的委托传递给ViewController C.

在视图控制器C中定义相同类型的委托

weak var delegate: ViewControllerBDelegate?

然后在导航到查看控制器c的视图控制器B中传递相同的委托

let vc = ViewControllerC()
vc.delegate = self.delegate
present(vc, animated: true, completion: nil)

编辑2

SWRevealViewController是不同的场景。 revealController有一个名为frontViewController的属性。如果你不推动任何其他控制器显示,它可以是你的ViewControllerA。使用frontViewController处理它是很棘手的,你应该确定frontController是否是ViewControllerA。

所以我建议你使用另一种方法与ViewControllerA进行通信。你可以使用NotificationCenter。

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中,当切换值为Changed时发布通知:

let userInfoDic:[String: Bool] = ["state": sender.isOn]
  // post a notification
  NotificationCenter.default.post(name: .updateMap, object: nil, userInfo: userInfoDic)
  

如果再次推送显示中的frontViewController。透露将启动   用于frontViewController的新ViewControllerA。在这种情况下你有   在UserDefault中设置设置,在ViewControllerA中读取此内容   设置。

使用UserDefaults:

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
}