Мост JavaScript iOS
Я работаю над приложением, в котором я собираюсь использовать оба HTML5 в UIWebView и собственную среду iOS. Я знаю, что я могу реализовать связь между JavaScript и Objective-C. Существуют ли библиотеки, которые упрощают реализацию этого сообщения? Я знаю, что есть несколько библиотек для создания родных приложений для iOS в HTML5 и javascript (например, AppMobi, PhoneGap), но я не уверен, есть ли библиотека, которая поможет создавать собственные приложения для iOS с интенсивным использованием JavaScript. Мне нужно:
- Выполнить JS-методы из Objective-C
- Выполнить Objective-C методы из JS
- Слушайте собственные события JS из Objective-C (например, событие готовности DOM)
Ответы
Ответ 1
Есть несколько библиотек, но я не использовал ни одну из них в больших проектах, поэтому вы можете попробовать их:
-
Тем не менее, я думаю, что это достаточно просто, чтобы вы могли попробовать сами. Я лично сделал именно это, когда мне нужно было это сделать. Вы также можете создать простую библиотеку, которая соответствует вашим потребностям.
1. Выполнить методы JS из Objective-C
Это действительно просто одна строка кода.
NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"];
Подробнее об официальной документации UIWebView.
2. Выполнить методы Objective-C от JS
К сожалению, это немного сложнее, потому что в Mac OSX не существует того же свойства (и класса) windowScriptObject, которое обеспечивает полную связь между ними.
Тем не менее, вы можете легко звонить с пользовательских URL-адресов javascript, например:
window.location = yourscheme://callfunction/parameter1/parameter2?parameter3=value
И перехватите это от Objective-C этим:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *URL = [request URL];
if ([[URL scheme] isEqualToString:@"yourscheme"]) {
// parse the rest of the URL object and execute functions
}
}
Это не так чисто, как должно быть (или с помощью windowScriptObject), но это работает.
3. Прослушайте нативные события JS из Objective-C (например, событие, готовое для DOM)
Из приведенного выше объяснения вы видите, что если вы хотите это сделать, вам нужно создать некоторый код JavaScript, прикрепить его к событию, которое вы хотите отслеживать, и вызвать правильный вызов window.location
который затем будет перехвачен.
Опять не чисто как положено, но работает.
Ответ 2
Рекомендуемый метод вызова цели c из JS в принятом ответе не рекомендуется. Один из примеров проблем: если вы делаете два последовательных последовательных вызова, один игнорируется (вы не можете быстро изменить местоположение).
Я рекомендую следующий альтернативный подход:
function execute(url)
{
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", url);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
Вы вызываете функцию execute
несколько раз, и поскольку каждый вызов выполняется в своем собственном iframe, они не должны игнорироваться при быстром вызове.
Кредиты этого парня.
Ответ 3
Обновление: Это изменилось в iOS 8. Мой ответ относится к предыдущим версиям.
Альтернативой, которая может заставить вас отказаться от хранилища приложений, является использование WebScriptObject.
Эти API-интерфейсы являются общедоступными в OSX, но не на iOS.
Вам необходимо определить интерфейсы для внутренних классов.
@interface WebScriptObject: NSObject
@end
@interface WebView
- (WebScriptObject *)windowScriptObject;
@end
@interface UIWebDocumentView: UIView
- (WebView *)webView;
@end
Вам нужно определить свой объект, который будет служить вашим WebScriptObject
@interface WebScriptBridge: NSObject
- (void)someEvent: (uint64_t)foo :(NSString *)bar;
- (void)testfoo;
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
+ (WebScriptBridge*)getWebScriptBridge;
@end
static WebScriptBridge *gWebScriptBridge = nil;
@implementation WebScriptBridge
- (void)someEvent: (uint64_t)foo :(NSString *)bar
{
NSLog(bar);
}
-(void)testfoo {
NSLog(@"testfoo!");
}
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
{
return NO;
}
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
{
return NO;
}
+ (NSString *)webScriptNameForSelector:(SEL)sel
{
// Naming rules can be found at: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/WebKit/Protocols/WebScripting_Protocol/Reference/Reference.html
if (sel == @selector(testfoo)) return @"testfoo";
if (sel == @selector(someEvent::)) return @"someEvent";
return nil;
}
+ (WebScriptBridge*)getWebScriptBridge {
if (gWebScriptBridge == nil)
gWebScriptBridge = [WebScriptBridge new];
return gWebScriptBridge;
}
@end
Теперь установите экземпляр в UIWebView
if ([uiWebView.subviews count] > 0) {
UIView *scrollView = uiWebView.subviews[0];
for (UIView *childView in scrollView.subviews) {
if ([childView isKindOfClass:[UIWebDocumentView class]]) {
UIWebDocumentView *documentView = (UIWebDocumentView *)childView;
WebScriptObject *wso = documentView.webView.windowScriptObject;
[wso setValue:[WebScriptBridge getWebScriptBridge] forKey:@"yourBridge"];
}
}
}
Теперь внутри вашего javascript вы можете позвонить:
yourBridge.someEvent(100, "hello");
yourBridge.testfoo();
Ответ 4
В iOS8 вы можете посмотреть на WKWebView вместо UIWebView. Это имеет следующий класс: WKScriptMessageHandler: Предоставляет метод для получения сообщений от JavaScript, запущенного на веб-странице.
Ответ 5
Это возможно с iOS7, checkout http://blog.bignerdranch.com/3784-javascriptcore-and-ios-7/
Ответ 6
Ваш лучший выбор - предложение Аппликаторов Титана. Они уже создали мост javascript Obj-C, используя механизм V8 engine JavascriptCore, используемый webkit. Он также с открытым исходным кодом, поэтому вы сможете загрузить его и поработать с Obj-C, как вам нравится.
Ответ 7
Взгляните на проект KirinJS: Kirin JS, который позволяет использовать Javascript для логики приложения и собственного пользовательского интерфейса, подходящего для платформы, на которой он выполняется на.
Ответ 8
Я создал библиотеку, такую как WebViewJavascriptBridge, но она больше похожа на JQuery, ее проще настроить и проще в использовании. Не полагается на jQuery (хотя, к его чести, если бы я знал, что WebViewJavascriptBridge существовал до написания этого, я мог бы просто немного сдержать перед погружением). Дайте мне знать, что вы думаете! jockeyjs
Ответ 9
Если вы используете WKWebView на iOS 8, посмотрите XWebView, который может автоматически открыть собственный интерфейс для javascript.