web-dev-qa-db-ja.com

Swift-プログラムで画面上のポイントをクリックします

tl; dr-画面上の特定のポイントでプログラムによってネイティブタッチを実行するにはどうすればよいですか?

Webビュー内には、iframeを含むHTMLがあるため、Webビューのコードと要素にはアクセスできず、JSへのサンディングマッサージも不可能です。特定の座標のWebビューにボタンがあります。プログラムでどのように押すことができますか?

21
Luda

タッチをシミュレートするには、あなたに代わってボタンをクリックできる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 })
3
Myles Eynon

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使用するバージョンによって異なります。ここでは強制アンラップを行っていますが、何が起こっているのかについての一般的な理解が得られるはずです。

2
JAL

また、ヒットテストを試します。

    let pointOnTheScreen = CGPointMake(50, 50)
    view.hitTest(pointOnTheScreen, withEvent: nil)
1
nferocious76

したがって、目的は、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
    }
}
1