有没有办法在 SwiftUI 中创建新的手势?

RPS*_*PSM 8 uikit ios swift swiftui

SwiftUI 缺少​​平移手势(即缩放和偏移),因此我试图创建一个。然而,手势结构似乎依赖于私有类。例如:

public struct PinchGesture: Gesture {

    public struct PinchGestureValue: Equatable {
        var scale: CGFloat
        var anchor: UnitPoint
        var offset: CGSize
        var isPinching: Bool
    }
    
    public typealias Value = PinchGestureValue
    public typealias Body = Never
    
    var minimumScaleDelta: CGFloat
    var minimumDistance: CGFloat
    var coordinateSpace: CoordinateSpace
    
    
    public init(minimumScaleDelta: CGFloat = 0.01, minimumDistance: CGFloat = 10, coordinateSpace: CoordinateSpace = .local) {
        self.minimumScaleDelta = minimumScaleDelta
        self.minimumDistance = minimumDistance
        self.coordinateSpace = coordinateSpace
    }
    
    public static func _makeGesture(gesture: _GraphValue<PinchGesture>, inputs: _GestureInputs) -> _GestureOutputs<PinchGestureValue> {
      // Unable to complete
    }

}
Run Code Online (Sandbox Code Playgroud)

此代码无法完成,因为 _GraphValue、_GestureInputs 和 _GestureOutputs 是私有的。在我完全屈服之前,我想看看是否有人找到了解决方法。

rob*_*off 4

SwiftUI 提供了以下默认实现_makeGesture

extension Gesture where Self.Value == Self.Body.Value {
  public static func _makeGesture(gesture: SwiftUI._GraphValue<Self>, inputs: SwiftUI._GestureInputs) -> SwiftUI._GestureOutputs<Self.Body.Value>
}
Run Code Online (Sandbox Code Playgroud)

这里的困难在于约束Self.Value === Self.Body.Value。这意味着您的手势body不能声明为 return some Gesture,因为some Gesture无法满足约束(即使它Value匹配)。所以你必须给出body一个特定的类型。最简单的解决方案是使用AnyGesture类型橡皮擦:

public struct PinchGesture: Gesture {

    ...

    public var body: AnyGesture<PinchGestureValue> {
        AnyGesture(
            DragGesture(minimumDistance: 0, coordinateSpace: .global)
               .map { PinchGestureValue($0) }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

在此代码中,Swift 可以推断PinchGesture.Value = PinchGestureValuePinchGesture.Body = AnyGesture<PinchGestureValue>。那么就可以证明,所以它可以使用SwiftUI 提供的AnyGesture<PinchGestureValue>.Value == PinchGesture.Value默认实现。_makeGesture

不幸的是,我怀疑您可以使用它来创建您的PinchGesture. 最终,您body仍然仅限于组合 SwiftUI 的原始手势,这不会让您访问当前UIEventUITouch对象。