Подтвердить что ты не робот

Swift - программный щелчок по точке на экране

tl; dr - Как я могу программно выполнить нативный контакт в определенной точке экрана?

Внутри веб-представления есть HTML, который содержит Iframe, поэтому код и элементы веб-представления недоступны, и обработка JS-сообщений не возможна. В определенных условиях на веб-странице есть кнопка. Как я могу нажать программно?

4b9b3361

Ответ 1

Для имитации касания вам нужно будет написать функцию 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 })

Ответ 2

Если вы не хотите имитировать касание на уровне 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, которую вы используете. Я делаю здесь принудительное разворачивание, но вы должны получить общее представление о том, что происходит.

Ответ 3

Таким образом, целью было имитировать событие сенсорного экрана в 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
    }
}

Ответ 4

Вы также можете попробовать тест:

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