Xamarin.iOS で UIWebView から C# のコードを呼び出す方法

まあ、

を Xamarin.iOS でやってみたという話なだけです。

サンプル

//MainViewController.cs

/* in MainViewController.designer.cs
[Outlet]
[GeneratedCodeAttribute ("iOS Designer", "1.0")]
MonoTouch.UIKit.UIWebView MyWebView { get; set; }
*/

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    
    MyWebView.LoadRequest(NSUrlRequest.FromUrl(NSUrl.FromString("http://www.hatena.ne.jp/")));

    // LoadFinished はイベント
    MyWebView.LoadFinished += (sender, e) => {
        if (String.Equals(MyWebView.Request.Url.Host, "b.hatena.ne.jp"))
        {
            new UIAlertView("Load Finished", "ページが表示されました", null, "Close").Show();
        }
    };

    // ShouldStartLoad は Delegate
    MyWebView.ShouldStartLoad = (webView, req, navType) =>
    {
        var permited = !String.Equals(req.Url.Host, "hatenablog.com");
        if (!permited)
        {
            new UIAlertView("ShouldStartLoad", “はてなブログは見ちゃダメ!", null, "Close").Show();
        } 

        return permited;
    };
}

画面に UIWebView を一つ貼り付けて、 www.hatena.ne.jp を表示してます。

はてなブックマーク(b.hatena.ne.jp) へ移動すると、ページ読み込み後に「ページが表示されました」とポップアップします。 はてなブログ(hatenablog.com) へ移動しようとすると、「はてなブログは見ちゃダメ!」とポップアップし、移動はキャンセルされます。

Objective-C の、webViewDidFinishLoad , shouldStartLoadWithRequest デリゲートが、Xamarin.iOS では、 LoadFinished , ShouldStartLoad に対応します。

注意点は、LoadFinished はイベントであるのに、 ShouldStartLoad は delegate であるという事です。

Obj-C のデリゲートは、Xamarin.iOS では全てイベントになっているのかなーと思っていましたが、 ShouldStartLoad のように「値を返す」必要があるものについては delegate になっているようです。

Xamarin.iOS の APIデザインについては、公式サイトに説明があります。

ガッツリ熟読した方がよさそうですねえ。

最後に、作ったサンプルを動かしてみます。

なんか LoadFinished が2回呼ばれてる。重複チェックしなきゃダメですね