web-dev-qa-db-ja.com

JavaScriptからObjective-Cを呼び出す方法は?

WebViewがあり、JavaScriptからObjective-Cのビューを呼び出したい。誰かが私がこれを行う方法を知っていますか?


私の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;
}

しかし、何も起こりません。

41
Obliviux

UIWebViewの標準的な回避策は、UIWebViewDelegateを設定し、メソッド webView:shouldStartLoadWithRequest:navigationType: 。 JavaScriptコードで、次のように、アプリに渡す情報をエンコードする偽のURLに移動します。

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

デリゲートメソッドで、これらの偽のURLを探し、必要な情報を抽出し、適切なアクションを実行し、NOを返してナビゲーションをキャンセルします。 performSelectorのフレーバー を使用して長時間の処理を延期するのがおそらく最善です。

52
Sixten Otto

JSからObjective Cを呼び出すwindow.locationメソッドはお勧めしません。問題の1つの例:すぐに連続して2つの呼び出しを行う場合、1つは無視されます(場所をすばやく変更できないため)-自分で試してください。

次の代替アプローチをお勧めします。

function execute(url) 
{
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", url);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;
}

execute関数を繰り返し呼び出します。各呼び出しは独自のiframeで実行されるため、すぐに呼び出される場合は無視しないでください。

this guy へのクレジット。

32
talkol

Obliviux、

あなたのコードは完璧なようです。

この問題の理由は、デリゲートをマップするのに失敗したためです。

どちらか

  1. WebViewのデリゲートを.xibファイルのファイル所有者に接続します

または

  1. 使用する webView.delegate = self;

viewDidLoadで。

ありがとう

4
sm abbas

ここで述べたように、UIWebviewDelegateのメソッドwebView:shouldStartLoadWithRequest:navigationType:を使用する必要があります。

このAPI http://code.google.com/p/jsbridge-to-cocoa/ はあなたのためにそれを行います。とても軽量です。 javascriptからObjective-Cに画像、文字列、配列を渡すことができます。

3
John

このアプローチには問題がありました。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()を呼び出す必要があります。この方法は私にとっては有効であり、おそらく同じ問題を抱えている人を助けるかもしれません!

2

これを確認してください- この(または他のJavaScript)関数を使用してXMLHttpRequestの応答を理解しますか? 、Objective Cを使用してajax js関数を呼び出し、完了後に応答を取得します。 javascriptで場所を変更するとトリガーされるため、場所を確認してjavascript呼び出しまたは実際のリクエストを知ることができます。

1
Tom

アプリを実行していると仮定すると、 PhoneGap がそれを実装する(または使用する)方法を見ることができます。 JSとOBJ-C間の往復通信をサポートするライブラリです。他のライブラリとソリューションもあります。

Webアプリ(ユーザーがMobile Safariからアクセスするもの)について話している場合、そこからObjective-Cにアクセスすることはできません。

1
Nosredna

これは今では非常に古い質問ですが、Googleから返され続けており、WebScripting非公式プロトコルという良い答えがあります。 Objective CオブジェクトをJavascriptに公開できます。

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

0
O'Rooney