我需要知道应该怎么做才能在 HTML 中使用 JavaScriptUIWebView
来通知 Objective-C 发生了一些事情?
更准确地说,我正在用 HTML 播放一些 JavaScript 动画,我需要提醒 Objective-C 代码动画已经结束。
我需要知道应该怎么做才能在 HTML 中使用 JavaScriptUIWebView
来通知 Objective-C 发生了一些事情?
更准确地说,我正在用 HTML 播放一些 JavaScript 动画,我需要提醒 Objective-C 代码动画已经结束。
似乎没有这样做的官方方法。然而,该 标准的 解决方法包括读取和解析传入的URL请求,基本上滚动你自己的序列化的消息传递协议。消息处理应该在webView:shouldStartLoadWithRequest:navigationType
视图控制器的方法中完成。
注意:有几个免费的库(PhoneGap、QuickConnect、JS-to-Cocoa Bridge)包装了这个功能(还有更多)。要重新发明轮子(或者知道它为什么是圆的,可以这么说),请继续阅读。
在 JavaScript 中,您将通过尝试导航到新 URL 来调用回调:
// In JavaScript
window.location = 'myapp:myaction:param1:param2'; // etc...
在 Objective-C 中,UIWebViewDelegate
在你的.h
文件中实现协议:
// 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 查询组合成 Objective-C 对象。
实际上对于 iOS 中的计时(可能不适用于 OSX?),如果window.location
在前一个window.location
调用执行之前进行了第二个调用,那么第一个window.location
调用就会丢失。我认为window.location
调用在调用后与 JavaScript 异步执行,如果在执行之前进行了另一个调用,它会取消第一个调用。
例如,在捕获触摸事件时,我见过ontouchstart
not get sent via window.location
,如果ontouchmove
事件发生后很快(例如手指快速滑动)。因此你的 Objective-C 没有得到ontouchstart
事件。这在原始 iPad 上比 iPad2 上的问题更大,我认为是因为处理速度。
zourtney 的回答是正确的,但忘了提一件事.. 需要通过以下方式将委托注册到 webview
- (void)viewDidLoad {
[super viewDidLoad]; --- instantiate _webview next .. then
_webview.delegate = self; //important .. needed to register webview to delegate
}
希望这可以帮助 .....
迅捷版
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
}
}