Swift - programmatically click on point in screen

谁说胖子不能爱 提交于 2020-04-08 18:57:19

问题


tl;dr- How can I programmatically perform a native touch in specific point on the screen?

Within the web view there is HTML that contains an Iframe, so the web view code and elements are not accessible and sanding massages to JS is not possible either. There is a button in the web view on specific coordinates. How can I press it programmatically?


回答1:


To simulate the touch you will need to write a javascript function in your web page that can click the button on your behalf.

Let's assume the button on the website loaded in the iFrame is coded as the following:

<a href="#" id="MagicButton" onclick="targetFunction();">Click Me!</a>

And the iFrame is coded like so in your webpage:

<iframe id="MyIFrame" src="http://www.stackoverflow.com" width="200" height="200"></iframe>

In your web page add the following javascript function to call the click event on the embedded button:

<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>

Going back to your Swift code, you will need to use the following API:

func evaluateJavaScript(_ javaScriptString: String,
      completionHandler completionHandler: ((AnyObject?,
                                 NSError?) -> Void)?) 

You can execute your javascript function by calling the following function after the page has loaded:

   myWKWebview.evaluateJavaScript("myJavaScriptFunction(argument1, argument2);",
                                                               completion:{ _ in })



回答2:


If you don't want to simulate the touch on the JavaScript level, you can use this extension on UITouch and UIEvent, just bridge it to 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)
}

Your syntax may vary depending on the version of Swift you use. I'm doing some forced-unwrapping here but you should get the general idea of what is happening.




回答3:


You also try hit test:

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



回答4:


So the objective was to simulate a touch screen event on a webView.

The structure is

ViewController-
  self.glassView-|
     self.webView-|
       self.view.

I've write this class but I don't yet test:

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
    }
}


来源:https://stackoverflow.com/questions/38075699/swift-programmatically-click-on-point-in-screen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!