从 appdelegate 更新视图控制器 - 最佳实践?

Posted

技术标签:

【中文标题】从 appdelegate 更新视图控制器 - 最佳实践?【英文标题】:update viewcontroller from appdelegate - best practice? 【发布时间】:2015-03-21 03:04:45 【问题描述】:

我正在使用 iBeacons 在 AppDelegate.swift 中实现 CoreLocation 方法(方法在 AppDelegate 中实现以确保应用程序后台功能)

在“ViewController.swift”附带的 SingleView 应用程序中,将数据从 AppDelegate 传递到 ViewController 以更新视图(例如 UIImages、UILabels 或 UITableViews)的最佳实践是什么?

我已经成功实现了两种不同的方法:

1) 委托,通过在 AppDelegate.swift 中触发 Viewcontroller 委托方法:

protocol BeaconLocationDelegate  func minorBeaconChanged(minorValue:NSNumber) 

var locationDelegate: BeaconLocationDelegate

locationDelegate?.minorBeaconChanged(nearestBeacon.minor)

ViewController.swift:

在 viewDidLoad 方法中:

(UIApplication.sharedApplication().delegate as AppDelegate).locationDelegate = self

(我觉得这看起来很丑 - 有没有更好的方法将此属性声明为委托?)

协议实现:

func minorBeaconChanged(minorValue: NSNumber) 
  // do fancy stuff here

2) 通过在 AppDelegate 中创建对 ViewController 的引用:

let viewController:ViewController = window!.rootViewController as ViewController
viewController.doSomethingFancy()

这两种方法对我来说都很好,但我认为通过委托的第一种方法更优雅,并且一旦你有多个 ViewControllers 是更好的选择。

有什么建议吗?

【问题讨论】:

【参考方案1】:

我认为第二种解决方案要容易得多。它还确保视图控制器不会耗尽内存(被“释放”)并且应用程序委托不会尝试联系不存在的对象。

另外,在多个控制器的情况下,我不理解委托参数。在这种情况下,您将不得不有多个代表,这确实不是一个理想的情况。或者您将不得不从外部将委托更改为不同的视图控制器 - 也不是很优雅且风险很大。

对于多视图控制器场景,我建议通过NSNotificationCenter 进行通知。这是一个松耦合,它确保只有那些需要做出反应的对象才能接收到消息。视图控制器应该在创建时开始监听通知,并在通知中心消失时从通知中心注销。

【讨论】:

这也是最佳做法吗?我认为委托将是最佳选择,部分原因在于 MVC 概念,其中对视图的更新主要由委托方法触发,从而将视图与模型分离。 我对处理 appdelegate 中的数据也不是很有信心。寻找将其移至单独班级的方法,但仍不确定如何。目标是从肮脏的 hack 转变为良好且可重用的代码。 建议的解决方案不违反 MVC。我们根本没有讨论过这个模型。这只是您希望将控制器与应用程序委托(应用程序的“全局”类)耦合到何种程度的问题。非常松散(通知)或紧密(保留的财产)。在您的用例中,没有理由反对紧密耦合。 您的第二条评论涉及一个不同的问题,也许您应该在单独的问题中解决。欢迎来到 ***。开始通过投票和/或接受答案来表示赞赏。【参考方案2】:

这个怎么样?

在 AppDelegate 中

var minorBeaconChanged: NSNumber -> () =  minor in 

并在位置更新时调用此方法。

在 ViewController 的 viewWillAppear 中

( UIApplication.sharedApplication().delegate as? AppDelegate )!.minorBeaconChanged =  minor in
//  Do with minor

编辑:2015 年 8 月 27 日

如果你想拥有多个观察者。

在 AppDelegate 中

var minorBeaconObservers: [ NSNumber -> () ] = []

并用'minor'调用minorBeaconObservers中的所有项目

在 ViewController 的 viewWillAppear 中

( UIApplication.sharedApplication().delegate as? AppDelegate )!.minorBeaconObservers.append( 
     minor in
    //  Do with minor
    
)

【讨论】:

这样minorBeaconChanged只能有1个观察者,但我现在正在使用它。

以上是关于从 appdelegate 更新视图控制器 - 最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章

更新 appDelegate 中的变量

从 AppDelegate 呈现特定的视图控制器

从 appDelegate 转到视图控制器

如何从 Appdelegate 导航到另一个视图控制器

从 appdelegate 展示一个视图控制器

无法从 appdelegate 推送视图控制器