从 UIWebView 中的 javascript 向 ObjectiveC 发送通知
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5671742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
send a notification from javascript in UIWebView to ObjectiveC
提问by mkto
I need to know what should be done to use JavaScript in a HTML sitting in UIWebView
to notify Objective-C that something has happened?
我需要知道应该怎么做才能在 HTML 中使用 JavaScriptUIWebView
来通知 Objective-C 发生了一些事情?
To be more exact, I'm playing some JavaScript animation in HTML and I need to alert the Objective-C code that the animation has ended.
更准确地说,我正在用 HTML 播放一些 JavaScript 动画,我需要提醒 Objective-C 代码动画已经结束。
回答by Courtney Christensen
There seems to be no official method of doing this. However, thestandardworkaroundinvolves reading and parsing incoming URL requests, basically rolling your own serialized messaging protocol. The message handling should be done in the webView:shouldStartLoadWithRequest:navigationType
method of your view controller.
似乎没有这样做的官方方法。然而,该标准的解决方法包括读取和解析传入的URL请求,基本上滚动你自己的序列化的消息传递协议。消息处理应该在webView:shouldStartLoadWithRequest:navigationType
视图控制器的方法中完成。
Note: there are several free libraries (PhoneGap, QuickConnect, JS-to-Cocoa Bridge) which wrap this functionality (plus do a whole lot more). To reinvent the wheel (or know why it's round, so to speak), read on.
注意:有几个免费的库(PhoneGap、QuickConnect、JS-to-Cocoa Bridge)包装了这个功能(还有更多)。要重新发明轮子(或者知道它为什么是圆的,可以这么说),请继续阅读。
From JavaScript, you will invoke the callback by attempting to navigate to a new URL:
在 JavaScript 中,您将通过尝试导航到新 URL 来调用回调:
// In JavaScript
window.location = 'myapp:myaction:param1:param2'; // etc...
In Objective-C, implement the UIWebViewDelegate
protocol in your .h
file:
在 Objective-C 中,UIWebViewDelegate
在你的.h
文件中实现协议:
// In your header file
@interface MyAppViewController : UIViewController <UIWebViewDelegate> {
...
}
@end
Next, implement the method in your .m
file:
接下来,在您的.m
文件中实现该方法:
// In your implementation file
-(BOOL)webView:(UIWebView *)webView2
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
// Break apart request URL
NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:@":"];
// Check for your protocol
if ([components count] > 1 &&
[(NSString *)[components objectAtIndex:0] isEqualToString:@"myapp"])
{
// Look for specific actions
if ([(NSString *)[components objectAtIndex:1] isEqualToString:@"myaction"])
{
// Your parameters can be found at
// [components objectAtIndex:n]
// where 'n' is the ordinal position of the colon-delimited parameter
}
// Return 'NO' to prevent navigation
return NO;
}
// Return 'YES', navigate to requested URL as normal
return YES;
}
Two important notes:
两个重要的注意事项:
Context: navigating to
myapp:whatever
will (of course) fail under any other context. Keep this in mind if you're loading cross-platform pages.Timing: if a second
window.location =
call is made before the first returns, it will get 'lost.' So, either lump your calls together, manually delay execution, or implement a queue which combines the above with JS queries into Objective-C objects.
上下文:导航到
myapp:whatever
将(当然)在任何其他上下文下失败。如果您正在加载跨平台页面,请记住这一点。时间:如果
window.location =
在第一次返回之前进行第二次调用,它将“丢失”。因此,要么将您的调用集中在一起,手动延迟执行,要么实现一个队列,将上述内容与JS 查询组合成 Objective-C 对象。
回答by Thorpedo
Actually for timing in iOS (maybe not for OSX?), if a second window.location
call is made before the previous window.location
call executes, then the first window.location
call gets lost. I think the window.location
call executes asynchronisely with the JavaScript after it is called, and if another call is made it before it executes, it cancels the first.
实际上对于 iOS 中的计时(可能不适用于 OSX?),如果window.location
在前一个window.location
调用执行之前进行了第二个调用,那么第一个window.location
调用就会丢失。我认为window.location
调用在调用后与 JavaScript 异步执行,如果在执行之前进行了另一个调用,它会取消第一个调用。
For example, when capturing touch events, I have seen ontouchstart
not get sent via window.location
, if an ontouchmove
event occurs to quickly afterwards (such as in a fast finger swipe). Thus your Objective-C doesn't get the ontouchstart
event. This is more of a problem on the original iPad than the iPad2, I assume because of processing speed.
例如,在捕获触摸事件时,我见过ontouchstart
not get sent via window.location
,如果ontouchmove
事件发生后很快(例如手指快速滑动)。因此你的 Objective-C 没有得到ontouchstart
事件。这在原始 iPad 上比 iPad2 上的问题更大,我认为是因为处理速度。
回答by Aneer Dev
zourtney's answer is correct , but forgot to mention one thing .. needed to register delegate to webview by
zourtney 的回答是正确的,但忘了提一件事.. 需要通过以下方式将委托注册到 webview
- (void)viewDidLoad {
[super viewDidLoad]; --- instantiate _webview next .. then
_webview.delegate = self; //important .. needed to register webview to delegate
}
hope this helps .....
希望这可以帮助 .....
回答by johisco
Swift Version
迅捷版
class ViewController: UIViewController,UIWebViewDelegate{
@IBOutlet weak var webviewInstance: UIWebView!
override func viewDidLoad() {
webviewInstance.delegate = self
super.viewDidLoad()
}
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let requestString: String = (request.URL?.absoluteString)!
var components: [AnyObject] = requestString.componentsSeparatedByString(":")
// Check for your protocol
if components.count > 1 && (String(components[0]) == "myapp") {
// Look for specific actions
if (String(components[1]) == "myaction") {
// Your parameters can be found at
// [components objectAtIndex:n]
}
return false
}
return true
}
}