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