iOS JavaScript мост - PullRequest
       4

iOS JavaScript мост

99 голосов
/ 28 февраля 2012

Я работаю над приложением, в котором я собираюсь использовать как HTML5 в UIWebView, так и нативный фреймворк iOS.Я знаю, что могу реализовать связь между JavaScript и Objective-C.Существуют ли библиотеки, которые упрощают реализацию этой коммуникации?Я знаю, что есть несколько библиотек для создания собственных приложений iOS в HTML5 и javascript (например, AppMobi, PhoneGap), но я не уверен, есть ли библиотека, которая поможет создавать собственные приложения iOS с интенсивным использованием JavaScript.Мне нужно:

  1. Выполнить методы JS из Objective-C
  2. Выполнить методы Objective-C из JS
  3. Прослушать собственные события JS из Objective-C (дляпример события готовности DOM)

Ответы [ 9 ]

149 голосов
/ 28 февраля 2012

Есть несколько библиотек, но я не использовал ни одну из них в больших проектах, поэтому вы можете попробовать их:

-

Однако я думаю, что это достаточно просто, чтобы вы могли попробовать сами.Я лично сделал именно это, когда мне нужно было это сделать.Вы также можете создать простую библиотеку, которая соответствует вашим потребностям.

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 вызов, который затем будет перехвачен.

Опять не чисто, как должно быть, но он работает.

57 голосов
/ 01 ноября 2012

Предложенный метод вызова цели 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, их нельзя игнорировать при быстром вызове.

Кредиты этому парню .

12 голосов
/ 12 сентября 2013

Обновление: Это изменилось в 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();
5 голосов
/ 18 сентября 2014

В iOS8 вы можете посмотреть на WKWebView вместо UIWebView . Это имеет следующий класс: WKScriptMessageHandler: Предоставляет метод для получения сообщений от JavaScript, запущенного на веб-странице.

3 голосов
/ 12 ноября 2013

Это возможно с iOS7, оформить заказ http://blog.bignerdranch.com/3784-javascriptcore-and-ios-7/

0 голосов
/ 28 апреля 2015

Если вы используете WKWebView на iOS 8, взгляните на XWebView , который может автоматически открывать собственный интерфейс для JavaScript.

0 голосов
/ 05 марта 2013

Я создал библиотеку наподобие WebViewJavascriptBridge, но она более похожа на JQuery, проще в настройке и проще в использовании. Не полагается на jQuery (хотя к его чести, если бы я знал, что WebViewJavascriptBridge существовал до написания этого, я мог бы просто немного сдержаться, прежде чем погрузиться в него). Дайте мне знать, что вы думаете! jockeyjs

0 голосов
/ 28 февраля 2012

Взгляните на проект KirinJS: Kirin JS , который позволяет использовать Javascript для логики приложения и собственного пользовательского интерфейса, соответствующего платформе, на которой он работает.

0 голосов
/ 28 февраля 2012

Ваш лучший выбор - предложение Appanelerators Titanium. Они уже создали JavaScript-мост Obj-C, используя V8 engine JavascriptCore engine, используемый webkit. Он также с открытым исходным кодом, так что вы сможете скачать его и поработать с Obj-C по своему усмотрению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...