Swift - 以编程方式单击屏幕中的点

时间:2016-06-28 12:02:08

标签: ios swift webview uitouch

tl; dr - 如何在屏幕上的特定点以编程方式执行本机触摸?

在Web视图中,HTML包含一个Iframe,因此无法访问Web视图代码和元素,也无法对JS进行打磨按摩。 Web视图中的特定坐标上有一个按钮。如何以编程方式按下它?

4 个答案:

答案 0 :(得分:3)

要模拟触摸,您需要在网页中编写一个javascript函数,可以代表您单击按钮。

我们假设iFrame中加载的网站上的按钮编码如下:

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

iFrame在您的网页中的编码方式如此:

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

在您的网页中添加以下javascript函数以调用嵌入按钮上的click事件:

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

答案 1 :(得分:2)

如果您不想模拟JavaScript级别的触摸,可以在UITouchUIEvent上使用this extension,只需将其桥接到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 :(得分:1)

因此,目标是在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
    }
}

答案 3 :(得分:1)

你也尝试点击测试:

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