如何观察全局变量的值并处理视图控制器中的更改



我正在我的iOS应用程序中使用通用链接,并且可以成功地将应用程序中的URL值存储为全局变量。这是在应用委托的早期完成的。这从启动到从后台重新打开应用程序时都有效。

然后将此 URL 作为源 URL 传递给 WKWebView。

问题是WKWebView的视图控制器已经加载,并且在我退出并返回之前不会检测到新的URL。

我制作了一段非常丑陋的代码,这些代码可以工作,但对于生产来说还不够好。它监视主线程外变量的变化,但通过重复循环和 1 秒的睡眠来完成,以避免 CPU 过度运行。

当全局变量的值不等于其默认值时,在视图控制器中进行 segue 的正确方法是什么?

我看过遗嘱,做了一个。但是由于我的变量是在视图控制器类之外定义的,因此我无法执行 segue。

// home made loop to look for a change in universal link
DispatchQueue.global().async {
repeat
{
sleep(1) // save CPU
}
while universalOverrideURL == "none"
DispatchQueue.main.sync {
print("S E G U E  I S  N E E D E D !")
}
}

有没有更好的方法可以应用,尊重 CPU?

有很多方法可以解决这个问题。 iOS原生方式是使用通知中心:

//Make your custom notification
extension Notification.Name {
static let myCustomValueUpdated = Notification.Name("myCustomValueUpdated")
}
//Post the notification when you the value
NotificationCenter.default.post(Notification(name: .myCustomValueUpdated, object: nil, userInfo: ["value": someNewValue]))
//Subscribe everywhere that needs to be interested in UserDefaults changes
let token = NotificationCenter.default.addObserver(forName: .myCustomValueUpdated, object: nil, queue: .main) { notification in
if let value = notification.userInfo["value"] {
//Do stuff with new value here
}
}

您还可以考虑创建一个服务来将值包装为您正在更改的值,然后使用观察者模式允许其他对象订阅该值中的更改。 我倾向于更喜欢这个解决方案,因为它 1) 可测试和可模拟,2) 强类型,3) 将内容移出您的应用程序委托,但如果您不关心任何这些,只需使用 NotificationCenter,因为它是最少的工作和易于理解的苹果模式。

您可以使用委托来通知视图控制器。

这是委托的接口:

@protocol UniversalOverrideURLObserver
func onURLChanged(url: String) -> Void
@end

您的视图控制器可以实现此接口:

class ViewController: UIViewController,  UniversalOverrideURLObserver {
}

然后,实例化 ViewController 的代码可以像这样执行 smth:

func addObserver(observer: UniversalOverrideURLObserver) -> Void {
self.observer = observer
}
func funcWhereValueChanges() {
// HERE your url changed    
self.observer.onURLChanged(url: newURL)
}
func funcWhereViewControllerShown() {
// HERE you are ready to present ViewController
let vc = ViewController()
self.addObserver(vc)
}