web-dev-qa-db-fra.com

Swift - cliquez par programme sur le point dans l'écran

tl; dr- Comment puis-je effectuer par programmation une touche native en un point spécifique de l'écran? 

La vue Web contient du code HTML contenant un Iframe. Le code et les éléments de la vue Web ne sont donc pas accessibles et les massages de ponçage sur JS ne sont pas non plus possibles. Il y a un bouton dans la vue Web sur des coordonnées spécifiques. Comment puis-je appuyer sur le programme?

18
Luda

Pour simuler le toucher, vous devrez écrire une fonction javascript dans votre page Web pouvant cliquer sur le bouton en votre nom. 

Supposons que le bouton du site Web chargé dans l'iFrame est codé comme suit:

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

Et l’iFrame est codé comme tel dans votre page Web:

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

Dans votre page Web, ajoutez la fonction javascript suivante pour appeler l'événement click sur le bouton incorporé:

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

Pour revenir à votre code Swift, vous devrez utiliser l'API suivante:

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

Vous pouvez exécuter votre fonction javascript en appelant la fonction suivante une fois la page chargée:

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

Si vous ne voulez pas simuler le contact au niveau JavaScript, vous pouvez utiliser cette extension sur UITouch et UIEvent, reliez-le simplement à 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)
}

Votre syntaxe peut varier en fonction de la version de Swift que vous utilisez. Je suis en train de faire du déballage forcé ici, mais vous devriez avoir une idée générale de ce qui se passe.

2
JAL

Vous essayez également le test de frappe:

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

L'objectif était donc de simuler un événement d'écran tactile sur une vue Web.

La structure est

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

J'ai écrit ce cours mais je n'ai pas encore 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
    }
}
1
Alessandro Ornano