tl; dr-画面上の特定のポイントでプログラムによってネイティブタッチを実行するにはどうすればよいですか?
Webビュー内には、iframeを含むHTMLがあるため、Webビューのコードと要素にはアクセスできず、JSへのサンディングマッサージも不可能です。特定の座標のWebビューにボタンがあります。プログラムでどのように押すことができますか?
タッチをシミュレートするには、あなたに代わってボタンをクリックできるJavaScript関数をWebページに記述する必要があります。
IFrameに読み込まれたWebサイトのボタンが次のようにコーディングされていると仮定します。
<a href="#" id="MagicButton" onclick="targetFunction();">Click Me!</a>
そしてiFrameはあなたのウェブページでそのようにコード化されています:
<iframe id="MyIFrame" src="http://www.stackoverflow.com" width="200" height="200"></iframe>
Webページに次のJavaScript関数を追加して、埋め込みボタンのクリックイベントを呼び出します。
<script>
function myJavaScriptFunction(){
//get handle for the iFrame element
var iFrame = document.getElementById('MyIFrame');
var htmlDoc = iFrame.contentDocument ? iFrame.contentDocument : iFrame.contentWindow.document;
var magicButton = htmlDoc.getElementById('MagicButton');
magicButton.click();
}
</script>
Swiftコードに戻ると、次のAPIを使用する必要があります。
func evaluateJavaScript(_ javaScriptString: String,
completionHandler completionHandler: ((AnyObject?,
NSError?) -> Void)?)
ページが読み込まれた後に次の関数を呼び出すことにより、JavaScript関数を実行できます。
myWKWebview.evaluateJavaScript("myJavaScriptFunction(argument1, argument2);",
completion:{ _ in })
JavaScriptレベルでタッチをシミュレートしたくない場合は、_ この拡張 をUITouch
およびUIEvent
で使用し、Swiftにブリッジするだけです。
func performTouchInView(view: UIView) {
let touch = UITouch(inView: view)
let eventDown = UIEvent(touch: touch)
touch.view!.touchesBegan(eventDown.allTouches()!, withEvent: eventDown)
touch.setPhase(.Ended)
let eventUp = UIEvent(touch: touch)
touch.view!.touchesEnded(eventUp.allTouches()!, withEvent: eventUp)
}
構文はSwift使用するバージョンによって異なります。ここでは強制アンラップを行っていますが、何が起こっているのかについての一般的な理解が得られるはずです。
また、ヒットテストを試します。
let pointOnTheScreen = CGPointMake(50, 50)
view.hitTest(pointOnTheScreen, withEvent: nil)
したがって、目的は、webViewのタッチスクリーンイベントをシミュレートすることでした。
構造は
ViewController-
self.glassView-|
self.webView-|
self.view.
このクラスは作成しましたが、まだテストしていません。
class ViewController: UIViewController,UIWebViewDelegate {
@IBOutlet weak var webView: UIWebView!
@IBOutlet weak var glassView: UIView!
var portionRect: CGRect!
override func viewDidLoad() {
super.viewDidLoad()
self.webView.delegate = self
let url = NSURL (string: "http://www.tiscali.it");
let requestObj = NSURLRequest(URL: url!)
self.webView.loadRequest(requestObj)
self.view.userInteractionEnabled = true
}
////////////////////////////////////////////////
// UIWebViewDelegate
func webViewDidStartLoad(webView: UIWebView) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
func webViewDidFinishLoad(webView: UIWebView) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
if self.webView.loading {
return
} else {
simulateTap()
}
}
func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}
func simulateTap() {
let pointOnTheScreen = CGPointMake(156.0, 506.6)
self.glassView.hitTest(pointOnTheScreen, withEvent: nil)
self.glassView.overlapHitTest(pointOnTheScreen, withEvent: nil)
print("tap on screen")
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if let touch = touches.first {
let touchLocation = touch.locationInView(self.view)
print("point touched: \(touchLocation)")
}
super.touchesBegan(touches, withEvent:event)
}
}
extension UIView {
func overlapHitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
// 1
if !self.userInteractionEnabled || self.hidden || self.alpha == 0 {
return nil
}
//2
var hitView: UIView? = self
if !self.pointInside(point, withEvent: event) {
if self.clipsToBounds {
return nil
} else {
hitView = nil
}
}
//3
for subview in self.subviews.reverse() {
let insideSubview = self.convertPoint(point, toView: subview)
if let sview = subview.overlapHitTest(insideSubview, withEvent: event) {
return sview
}
}
return hitView
}
}