UIWebViewでリンク長押し時のActionSheet
UIWebViewはデフォルトで、リンクを長押ししてるとActionSheetが出てきます。選択肢がOpenとCopyしかないので、実質あまり意味がなかったりしますが。
なのでこのActionSheetのボタンをアプリでカスタマイズしたい諸兄も多いことでしょう。
そんなときのTips。
まず問題は長押しされたことの検知と、長押しされたリンクのURLの取得。相変わらず、普通にやるとActionSheetが表示されたことすら検知することができません。GestureRecognizerを当てれば長押しされたことだけはわかりますが、それだとリンクURLを抜き出すことが不可能(だと思う)なので、UIWebViewの仕組みを使いたいところです。
私がやったチカラ押しな方法は次の通り。
- NSObjectのrespondsSelectorをmethod swizzling。
置き換えたメソッドの中でtouchCalloutEnabledを監視させる。 touchCalloutEnabledでActionSheetを出すべきかどうかを判断させているようなので、これが呼ばれた=ActionSheetの出番、という判断にできる。 - UIActionSheetのshowInView:をmethod swizzling。touchCalloutEnabledが呼ばれた直後のshowInView:はUIWebViewが出そうとしているので、それを出さない(捨てて)、独自にActionSheetを表示する。
長押しされたリンクのURLはActionSheetのtitleになっているので、それを使う。
というゴリ押しな方法で、とりあえず独自ActionSheetが出せる。
注意点はshowInView:でUIWebViewが表示しようとしたActionSheetを捨てるところ。なにもしないまま放っておくと、ActionSheetが閉じるのを待っているのか、UIWebViewが動かなくなる。仕方ないのでキャンセルボタンが押されたかのように
- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo} actionSheet:clickedButtonAtIndex:
- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo} actionSheet:willDismissWithButtonIndex:
- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo} actionSheet:didDismissWithButtonIndex:
を呼び出してあげると忘れてくれます。
相当ごり押しな方法ですが、なんとか目的達成。もっとスマートな方法があれば誰か教えてください…
ちなみに、ActionSheetを出さないのは
[webView stringByEvaluatingJavaScriptFromString:@”document.documentElement.style.webkitTouchCallout = ‘none’;”]
とやるだけで簡単にブロックできます。
-
takemasa5の投稿です