Swift - программный щелчок по точке на экране
tl; dr - Как я могу программно выполнить нативный контакт в определенной точке экрана?
Внутри веб-представления есть HTML, который содержит Iframe, поэтому код и элементы веб-представления недоступны, и обработка JS-сообщений не возможна. В определенных условиях на веб-странице есть кнопка. Как я могу нажать программно?
Ответы
Ответ 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)