尝试在控制器之间传递信息失败,但可以从 AppDelegate 到控制器
Posted
技术标签:
【中文标题】尝试在控制器之间传递信息失败,但可以从 AppDelegate 到控制器【英文标题】:Trying to pass information between controllers fails, yet works from AppDelegate to controller 【发布时间】:2017-05-23 16:48:03 【问题描述】:我有两个 UIViewController,vc1 和 vc2。 vc1 嵌入在 UIViewController 中,UIViewController 嵌入在 UITabBarController 中,但 vc2 没有嵌入。
如何将信息从 vc2 传递到 vc1?用户执行操作后,数据被保存并且 vc2 简单地关闭,因此没有传递信息的 segue。显然我无法通过导航堆栈或 TabController 引用 vc1。
我可以保存到 AppDelegate,但我知道这不是一个好习惯。
这是我用来将信息从 AppDelegate 传递到 vc1 的代码,我在 vc2 中尝试过,但显然失败了。:
let tabBarController = window!.rootViewController as! UITabBarController
if let tabBarViewControllers = tabBarController.viewControllers
let navPostViewController = tabBarViewControllers[0] as! UINavigationController
let user = User(context: managedObjectContext)
if user.userID != nil
print("User is loggedIn")
isUserLoggedIn = true
else
print("User is not loggedIn")
isUserLoggedIn = false
let postViewController = navPostViewController.topViewController as! PostViewController
postViewController.managedObjectContext = managedObjectContext
【问题讨论】:
使用 AppDelegate 来保存这样的关键数据本质上没有任何问题。您还可以使用单例来保存您的数据模型。有些人会提倡写入 UserDefaults 来保存数据——但这似乎是登录状态等动态数据的错误方法。有些人肯定会反对这些方法 - 但您必须找到最适合您的方案的方法 VC1 是否存在 VC2(例如模态)?如果是这样,定义协议让 VC2 通知它的代理一些动作。然后,当 VC1 呈现 VC2 时,将 VC1 设置为 VC2 的代理。这比浏览视图控制器层次结构和/或使用应用程序委托(或任何其他对象)来保存通过 b/w VC2 和 VC1 传递的属性要好得多。delegate
绝对是您场景中更好的方式,也是苹果推荐的方式。
@Rob 你的冠军。自从我开始开发以来,我一直在关注你。
这可能是 Passing Data between View Controllers 的副本。看到这个Swift answer
【参考方案1】:
首先,我从来没有养成使用 segue 传递信息的习惯。我会建议您在需要在两个对象之间传递数据时实现委托模式。它干净了很多。
例如,假设您想在 LoginViewController 和 PostViewController 之间传递数据:
protocol LoginViewControllerDelegate:NSObjectProtocol
func userDidLogin(data:String)
class LoginViewController:UIViewController
weak var delegate:LoginViewControllerDelegate?
...
@IBAction func loginButtonPressed(sender:UIButton)
//Perform login logic here
//If successful, tell the other controller or the 'delegate'
self.delegate?.userDidLogin(data:"Some data....")
class PostViewController:UIViewController, LoginViewControllerDelegate
func userDidLogin(data:String)
print("Got data from login controller: \(data)")
//How you might use this
loginViewController.delegate = postViewController
要记住的一个警告是永远不要尝试在两个对象之间进行强引用,即不要让对象相互保持,否则会导致内存泄漏。
【讨论】:
除非它是一个class
协议,否则你不能使它成为weak
。此外,如果它确实有 weak
引用,我不会将其设为隐式展开的可选项(否则,如果 delegate
是 nil
,应用程序将崩溃)。使用delegate?.userDidLogin(...)
语法更安全。例如。 gist.github.com/robertmryan/3d59608857f6b3797bf14dabb51a4a69
你说得对,我只是看了一下我的一些旧代码,协议确实必须从一个类扩展,就我而言,我只是扩展了NSObjectProtocol
,所以我对其进行了编辑以反映这一点.还对隐式展开的可选进行了更新。
终于掌握了协议/委托的速度。这就像一个魅力。谢谢!以上是关于尝试在控制器之间传递信息失败,但可以从 AppDelegate 到控制器的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PageViewController 和 ViewController 之间传递数据?