无法将Obj-C观察器转换为Swift语法

时间:2017-01-02 22:11:40

标签: ios objective-c swift webview nsnotificationcenter

此处的目标是在webView的网址发生变化时进行检测。由于WKWebView类的didCommitdidStartProvisionalNavigation函数在使用WebView中的某些元素时似乎总是闪现,我现在必须添加一个观察者来获取WebView&# 39;网址值的变化。

到目前为止,我已创建了名为checkURL的自己的通知扩展程序:

迅速进展

extension Notification.Name {
    static let checkURL = Notification.Name("checkURL")
}

NotificationCenter.default.post(name: .checkURL, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(getter: webView.url), name: .checkURL, object: webView.url)

Objective-C解决方案(KVO)

// Add an observer
[webView_ addObserver:self forKeyPath:@"URL" options:NSKeyValueObservingOptionNew context:NULL];

// Method that gets called when the URL value changes
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    // Code
}

如果URL值发生变化,我将如何应用Objective-C代码来触发函数?我仍然试图围绕通知以及它们如何处理对象值,所以任何解释都会非常有用!

感谢您阅读!

编辑:为了清理问题,我将重新提出问题:

由于didCommitdidStartProvisionalNavigation似乎总是无法解决(特别是在使用基于JavaScript的网站以及PHP时),您会不断看到网址被更改使用#和诸如此类的符号;但是,如前所述,内置的WKWebView功能似乎无法捕获这些功能。所以我在这里尝试做的是找到一种解决方法来捕获对URL所做的任何类型的更改,无论它是否只是#等等。最好保持代码完全是Swift - 如我仍在学习。 :)

1 个答案:

答案 0 :(得分:2)

首先,请原谅这个答案中的(很多)假设,但我无法评论要求澄清。

其次,我建议给NSNotificationCenter reference一个好读。另外,如果我没记错的话,this writeup关于通知的内容对我来说非常有帮助。

现在到实际代码。如果我理解你的困境(除了必须一起使用Objective-C和Swift,这总是很有趣),你试图在URL更改时发出通知,以便你的Swift代码可以对新URL做一些事情

由于您的快速代码正在倾听通知,您不希望将其发布到那里。相反,通知应该发布在KVO回调中,如下所示:

// I have also changed the 'URL' to 'url' as I suspect that KVO is case-sensitive
// and replaced NULL with nil as it is generally a better practice to use it.
[webView_ addObserver:self forKeyPath:@"url" options:NSKeyValueObservingOptionNew context:nil];

// Method that gets called when the URL value changes
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (sender == webView_ && [keyPath isEqualToString:@"url"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"checkURL" object:self];
    }
}

这会将通知发送给任何观察者,例如Swift类。 Swift代码必须改为:

extension Notification.Name {
    static let checkURL = Notification.Name("checkURL")
}

// Notice that the call to post(name:object:) has been removed.

// The 'object' parameter is only used for filtering out the sender of the notification.
NotificationCenter.default.addObserver(self, selector: #selector(doSomething(notification:)), name: .checkURL, object: nil)

// We can get the notification in the first parameter.
func doSomething(notification: Notification) {
    // Do something, like reading the URL from the web view.
}

现在,如果您在Swift代码中引用了webview,则可以在发布通知时传递userInfo参数中的值,如下所示:

[[NSNotificationCenter defaultCenter] postNotificationName:@"checkURL" object:self userInfo:@{ @"url" : webView.url }];

然后您可以在通知回调中读取userInfo:

func doSomething(notification: Notification) {
    let url = notification.userInfo["url"]
    // Do something with the url.
}