我需要知道如何在UIWebView
中的HTML中使用JavaScript来通知Objective-C发生了什么事情?
更确切地说,我正在用HTML播放一些JavaScript动画,我需要提醒动画结束的Objective-C代码。
答案 0 :(得分:46)
似乎没有官方方法可以做到这一点。但是,the standard workaround涉及读取和解析传入的URL请求,基本上是滚动您自己的序列化消息传递协议。消息处理应在视图控制器的webView:shouldStartLoadWithRequest:navigationType
方法中完成。
注意:有几个免费库(PhoneGap,QuickConnect,JS-to-Cocoa Bridge)包含此功能(另外还有更多功能)。要重新发明轮子(或者知道为什么它是圆的,可以这么说),请继续阅读。
从JavaScript中,您将尝试导航到新网址来调用回调:
// In JavaScript
window.location = 'myapp:myaction:param1:param2'; // etc...
在Objective-C中,在.h
文件中实施UIWebViewDelegate
协议:
// In your header file
@interface MyAppViewController : UIViewController <UIWebViewDelegate> {
...
}
@end
接下来,在.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;
}
两个重要的注释:
上下文:导航到myapp:whatever
(当然)会在任何其他情境下失败。如果您要加载跨平台页面,请记住这一点。
计时:如果在第一次返回之前进行了第二次window.location =
调用,则会“丢失”。因此,要么将你的呼叫混为一谈,要么手动延迟执行,要么实现一个将上述内容与JS queries into Objective-C objects结合起来的队列。
答案 1 :(得分:3)
实际上对于iOS中的计时(可能不适用于OSX?),如果在上一次window.location
调用执行之前进行了第二次window.location
调用,则第一次window.location
调用会丢失。我认为window.location
调用在调用后与JavaScript异步执行,如果在执行之前进行了另一次调用,它将取消第一个调用。
例如,在捕获触摸事件时,我看到ontouchstart
未通过window.location
发送,如果之后很快发生ontouchmove
事件(例如在快速手指滑动中) 。因此,您的Objective-C无法获得ontouchstart
事件。原来iPad上的问题比iPad2更多,我假设是因为处理速度快。
答案 2 :(得分:1)
zourtney的回答是正确的,但忘了提一件事......需要通过
注册代表到webview- (void)viewDidLoad {
[super viewDidLoad]; --- instantiate _webview next .. then
_webview.delegate = self; //important .. needed to register webview to delegate
}
希望这有助于.....
答案 3 :(得分:0)
Swift版本
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
}
}