【问题标题】:Force Touch/ 3D Touch in XCUITestXCUITest 中的 Force Touch/3D Touch
【发布时间】:2018-08-31 00:42:40
【问题描述】:

我正在尝试为 iOS 应用添加强制触摸自动化。我查看了 Apple 文档以解决同样的问题,但找不到任何有用的东西。我们可以从辅助触摸中进行强制触摸,但我正在寻找像 tap() 动作这样简单的东西。有什么可以用于 forceTouch 的吗?

任何帮助将不胜感激。谢谢!

【问题讨论】:

标签: ios swift ui-automation xcuitest force-touch


【解决方案1】:

使用press(forDuration)怎么样?

press(forDuration:)

向为元素计算的可命中点发送长按手势,并保持指定的持续时间。

https://developer.apple.com/documentation/xctest/xcuielement/1618663-press

【讨论】:

  • 我已经试过了。但它没有用。它就像在元素上正常点击一样。
  • 您的手势识别器是否配置为接受强制触摸?为了触发对文本字段的强制触摸,我通常使用 2 秒的持续时间。
  • 是的,它已配置。我可以使用我的 mac 触控板在模拟器中强制触摸。在运行 UIAutomation 测试时,我想执行强制触摸。我试过press(forDuration),但没有用。
【解决方案2】:

与触摸关联的原始力值在UITouch 对象的force 属性中可用。您可以将该值与maximumPossibleForce 属性中的值进行比较,以确定相对的力。

//Without this import line, you'll get compiler errors when implementing your touch methods since they aren't part of the UIGestureRecognizer superclass
//Without this import line, you'll get compiler errors when implementing your touch methods since they aren't part of the UIGestureRecognizer superclass
import UIKit.UIGestureRecognizerSubclass

//Since 3D Touch isn't available before iOS 9, we can use the availability APIs to ensure no one uses this class for earlier versions of the OS.
@available(iOS 9.0, *)
public class ForceTouchGestureRecognizer: UIGestureRecognizer {
  //Because we don't know what the maximum force will always be for a UITouch, the force property here will be normalized to a value between 0.0 and 1.0.
  public private(set) var force: CGFloat = 0.0
  public var maximumForce: CGFloat = 4.0

  convenience init() {
    self.init(target: nil, action: nil)
  }

  //We override the initializer because UIGestureRecognizer's cancelsTouchesInView property is true by default. If you were to, say, add this recognizer to a tableView's cell, it would prevent didSelectRowAtIndexPath from getting called. Thanks for finding this bug, Jordan Hipwell!
  public override init(target: Any?, action: Selector?) {
    super.init(target: target, action: action)
    cancelsTouchesInView = false
  }

  public override func touchesBegan(_ touches: Set, with event: UIEvent) {
    super.touchesBegan(touches, with: event)
    normalizeForceAndFireEvent(.began, touches: touches)
  }

  public override func touchesMoved(_ touches: Set, with event: UIEvent) {
    super.touchesMoved(touches, with: event)
    normalizeForceAndFireEvent(.changed, touches: touches)
  }


  public override func touchesEnded(_ touches: Set, with event: UIEvent) {
    super.touchesEnded(touches, with: event)
    normalizeForceAndFireEvent(.ended, touches: touches)
  }

  public override func touchesCancelled(_ touches: Set, with event: UIEvent) {
    super.touchesCancelled(touches, with: event)
    normalizeForceAndFireEvent(.cancelled, touches: touches)
  }

  private func normalizeForceAndFireEvent(_ state: UIGestureRecognizerState, touches: Set) {
    //Putting a guard statement here to make sure we don't fire off our target's selector event if a touch doesn't exist to begin with.
    guard let firstTouch = touches.first else { return }

    //Just in case the developer set a maximumForce that is higher than the touch's maximumPossibleForce, I'm setting the maximumForce to the lower of the two values.
    maximumForce = min(firstTouch.maximumPossibleForce, maximumForce)

    //Now that I have a proper maximumForce, I'm going to use that and normalize it so the developer can use a value between 0.0 and 1.0.
    force = firstTouch.force / maximumForce

    //Our properties are now ready for inspection by the developer. By setting the UIGestureRecognizer's state property, the system will automatically send the target the selector message that this recognizer was initialized with.
    self.state = state
  }

  //This function is called automatically by UIGestureRecognizer when our state is set to .Ended. We want to use this function to reset our internal state.
  public override func reset() {
    super.reset()
    force = 0.0
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    相关资源
    最近更新 更多