Как вызвать Objective-C из Javascript?

У меня есть WebView, и я хочу вызвать представление в Objective-C из JavaScript. Кто-нибудь знает, как я могу это сделать?


У меня этот код в моем ViewController:

- (BOOL)webView:(UIWebView *)webView2 
 shouldStartLoadWithRequest:(NSURLRequest *)request 
 navigationType:(UIWebViewNavigationType)navigationType {

 NSString *requestString = [[request URL] absoluteString];
 NSArray *components = [requestString componentsSeparatedByString:@":"];

 if ([components count] > 1 && 
  [(NSString *)[components objectAtIndex:0] isEqualToString:@"myapp"]) {
  if([(NSString *)[components objectAtIndex:1] isEqualToString:@"myfunction"]) 
  {

   NSLog([components objectAtIndex:2]); [[Airship shared] displayStoreFront]; //<- This is the code to open the Store
   NSLog([components objectAtIndex:3]); // param2
   // Call your method in Objective-C method using the above...
  }
  return NO;
 }

 return YES; // Return YES to make sure regular navigation works as expected.
}

И в Javascript:

function store(event)
{
    document.location = "myapp:" + "myfunction:" + param1 + ":" + param2;
}

Но ничего не происходит.

Ответ 1

Стандартным обходным решением для UIWebView является установка UIWebViewDelegate и реализация метода webView:shouldStartLoadWithRequest:navigationType:. В своем JavaScript-коде перейдите к некоторому фальшивому URL-адресу, который кодирует информацию, которую вы хотите передать в ваше приложение, например:

window.location = "fake://myApp/something_happened:param1:param2:param3";

В своем методе делегата найдите эти поддельные URL-адреса, извлеките необходимую информацию, выполните любые действия и верните NO, чтобы отменить навигацию. Лучше всего, если вы отложите длительную обработку, используя некоторый вкус performSelector.

Ответ 2

Метод window.location вызова объекта 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

Obliviux,

Ваш код кажется идеальным.

Причиной проблемы является то, что вы должны были пропустить карту для делегирования.

Либо

  • Подключите делегат webView к владельцу файла в файле .xib.

или

  • Используйте webView.delegate = self;

в viewDidLoad.

Спасибо

Ответ 4

Как и люди, упомянутые здесь, вы должны использовать метод webView: shouldStartLoadWithRequest: navigationType: из UIWebviewDelegate.

Этот api http://code.google.com/p/jsbridge-to-cocoa/ делает это за вас. Это очень легкий вес. Вы можете передавать изображения, строки и массивы с javascript на objective-C.

Ответ 5

У меня возникла проблема с этим подходом: я хотел отправить несколько сообщений на устройство iphone, но казалось, что они были "перекрыты", поскольку они не могли обрабатывать все из них последовательно.

Пример: при выполнении этого кода:

window.location = "app://action/foo";
window.location = "app://action/bar";

Действие foo никогда не выполнялось.

Мне нужно было сделать следующее:

waitingForMessage = false;

function MsgProcessed(){
    waitingForMessage = false;
}

function SyncLaunchURL(url){
    if (waitingForMessage){
        setTimeout(function(){SyncLaunchURL(url)},100);
    }else{
        window.location = url
        waitingForMessage = true;   
    }
}

SyncLaunchURL("app://action/foo");
SyncLaunchURL("app://action/bar");

При таком подходе iphone должен вызвать MsgProcessed() после обработки вызова. Этот способ работает для меня, и, возможно, помогает кому-то с той же проблемой!

Ответ 6

Предполагая, что вы делаете приложение, вы можете посмотреть, как PhoneGap реализует это (или даже использует его). Это библиотека, которая поддерживает обратную связь между JS и OBJ-C. Существуют и другие библиотеки и решения.

Если вы говорите о веб-приложении (что-то пользователь получает от Mobile Safari), вы не можете добраться до Objective-C оттуда.

Ответ 7

Проверьте это - понимание ответов XMLHttpRequest с использованием этой функции (или других javascript)?, используя объектив C для вызова функции ajax js и получив ответ после нее вы знаете, что трюк заключается в том, что веб-просмотр будет срабатывать при изменении местоположения в javascript, чтобы вы могли проверить местоположение, чтобы узнать его свой javascript-вызов или реальный запрос.

Ответ 8

Хотя сейчас это очень старый вопрос, он продолжает возвращаться Google, и сейчас есть хороший ответ: неофициальный протокол WebScripting. Это позволяет вам выставить объектный объект C в Javascript.

http://developer.apple.com/library/safari/documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html#//apple_ref/doc/uid/30001215-BBCBFJCD