我一直在研究一個概念驗證應用程序,它利用Objective C(iOS 7)和JavaScript之間的雙向通信,使用WebKit JavaScriptCore框架。我終於能夠按預期工作,但遇到了UIWebView失去對我通過JSContext創建的iOS對象的引用的情況。UIWebView JavaScript失去對iOS的引用JSContext命名空間(對象)
的應用程序是一個有點複雜,這裏有最基礎的:
- 我跑(CocoaHTTPServer)iOS設備上的Web服務器
- 的UIWebView的最初加載遠程URL,併爲後來重定向回
localhost
作爲應用流程的一部分(認爲的OAuth) - 的HTML頁面,該應用程序的主機(本地主機)的應該跟我的iOS代碼JavaScript的
這裏的iOS的身邊,我的ViewController的.h
:
#import <UIKit/UIKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
// These methods will be exposed to JS
@protocol DemoJSExports <JSExport>
-(void)jsLog:(NSString*)msg;
@end
@interface Demo : UIViewController <UserInfoJSExports, UIWebViewDelegate>
@property (nonatomic, readwrite, strong) JSContext *js;
@property (strong, nonatomic) IBOutlet UIWebView *webView;
@end
以及在相關的視圖控制器的.m
的部分:
-(void)viewDidLoad {
[super viewDidLoad];
// Retrieve and initialize our JS context
NSLog(@"Initializing JavaScript context");
self.js = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// Provide an object for JS to access our exported methods by
self.js[@"ios"] = self;
// Additional UIWebView setup done here...
}
// Allow JavaScript to log to the Xcode console
-(void)jsLog(str) {
NSLog(@"JavaScript: %@", str);
}
這裏是(簡化這個問題的緣故),HTML/JS的一面:
<html>
<head>
<title>Demo</title>
<script type="text/javascript">
function setContent(c, noLog){
with(document){
open();
write('<p>' + c + '</p>');
close();
}
// Write content to Xcode console
noLog || ios.jsLog(c);
}
</script>
</head>
<body onload="javascript:setContent('ios is: ' + typeof ios)">
</body>
</html>
現在,幾乎在所有情況下,這工作很漂亮,我看到ios is: object
無論是在一個UIWebView和Xcode的CON唯一。很酷。但是,在一個特定的情況下,時間的100%,這失敗一定數量的UIWebView的重定向後,一旦上述頁面最後裝入它說:
的IOS是:未定義
...並且JS邏輯的其餘部分退出,因爲隨後調用ios.jsLog
中的setContent
函數會導致未定義的對象異常。
因此,最後我的問題:什麼可能會導致JSContext丟失?我通過JavaScriptCore的.h文件中的「文檔」挖掘並發現,應該發生這種情況的唯一方法是,如果沒有更多strong
引用JSContext
,但在我的情況下,我擁有自己的一個,所以doesn看起來不錯。
我唯一的另一個假設是,它與在我取得JSContext
參考的方式做:我知道,這可能不是蘋果官方支持
self.js = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
,儘管我確實發現至少有一位說他有一個蘋果認可的應用程序使用這種方法。
編輯
我應該提,我實現UIWebViewDelegate
檢查JSContext後的UIWebView的每個重定向正是如此:
-(void)webViewDidFinishLoad:(UIWebView *)view{
// Write to Xcode console via our JSContent - is it still valid?
[self.js evaluateScript:@"ios.jsLog('Can see JS from obj c');"];
}
這適用於所有的情況下,即使我的網頁終於加載並報告ios is: undefined
上述方法同時將Can see JS from obj c
寫入Xcode控制檯。這似乎表明JSContext仍然有效,並且由於某種原因,它從JS中不再可見。
道歉很囉嗦的問題,對這個這麼少的文檔,在那裏,我想更多的信息,我可以提供,效果更佳。
嗨Madbreaks,我有相關的JS和IOS之間的通信問題。如果您有任何想法解決,請讓我知道。下面是我的鏈接「http://stackoverflow.com/questions/27120280/communication-between-javascript-and-objective-c-ios」 – Mahesh