Force Touch/3D Touch в XCUITest

Я пытаюсь добавить автоматизацию принудительного касания для приложения iOS. Я просмотрел документы Apple по той же проблеме, но не нашел ничего полезного. Мы можем сделать принудительное прикосновение из вспомогательного прикосновения, но я ищу что-то столь же простое, как действие tap(). Есть ли что-нибудь, что мы можем использовать для forceTouch?

Любая помощь будет оценена. Спасибо!


person Kushal Jogi    schedule 21.03.2018    source источник
comment
developer.apple.com/library/content/documentation/   -  person liquid    schedule 21.03.2018
comment
@slickdaddy Я реализовал это в коде разработки. Я хочу запустить UITest Automation с помощью xctest framework.   -  person Kushal Jogi    schedule 21.03.2018


Ответы (2)


Необработанное значение силы, связанное с касанием, доступно в свойстве force. объекта UITouch. Вы можете сравнить это значение со значением в свойстве 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
  }
}
person Fabian    schedule 17.04.2018

как насчет использования press(forDuration)?

press(forDuration:)

Отправляет жест длительного нажатия на точку попадания, вычисленную для элемента, удерживая указанную продолжительность.

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

person ablarg    schedule 10.04.2018
comment
Я пробовал это. Но это не сработало. Это действует как обычное нажатие на элемент. - person Kushal Jogi; 16.04.2018
comment
Настроен ли ваш распознаватель жестов на прием силового прикосновения? Чтобы вызвать принудительное касание текстового поля, я обычно использую 2-секундную продолжительность. - person ablarg; 16.04.2018
comment
Да настраивается. Я могу вызвать прикосновение в симуляторе с помощью трекпада моего Mac. Пока я запускаю тесты UIAutomation, я хочу выполнить принудительное касание. Я пробовал press(forDuration), но не получилось. - person Kushal Jogi; 16.04.2018