通过一个ObservableObject向下传递GestureState属性

时间:2019-08-09 21:09:29

标签: swiftui

我有一个ObservableObject,它的成员属性带有@GestureState包装器。在我的视图中,如何获得对GestureState属性的访问权限?

我已经尝试过将点符号与$绑定一起使用,以尝试公开GestureState,但事实并非如此

我的AppState ObservableObject

class AppState: ObservableObject {
    let objectWillChange = ObservableObjectPublisher()

    @GestureState var currentState: LongPressState = .inactive

    public enum LongPressState: String {
        case inactive = "inactive"
        case pressing = "pressing"
        case holding = "holding"
    }
}

该对象在我的代码中的实现:

@ObservedObject var appState: AppState
.
.
.
let longPress = LongPressGesture(minimumDuration: minLongPressDuration)
   .sequenced(before: LongPressGesture(minimumDuration: 5))
   .updating(appState.$currentState) { value, state, transaction in
      switch value {
      case .first(true):
         state = .pressing
      case .second(true, false):
         state = .holding
      default:
         state = .inactive
      }
}

我实际上在此View中没有遇到任何构建时错误,但是它使层次结构更高的View无效。如果我将@ObservedObject替换为本地@GestureState属性,那么它将正常工作。

1 个答案:

答案 0 :(得分:0)

我找到了一种很好的解决方法。

这个想法很简单:您有两次currentState

  1. GestureState的身份出现在您的视图中
  2. 在您的ObservableObject类中以Published

这是必须的,因为只能在视图中声明GestureState。现在唯一要做的就是以某种方式同步它们。

这是一种可能的解决方案:(使用onChange(of:)

class AppState: ObservableObject {

    @Published var currentState: LongPressState = .inactive
    
    enum LongPressState: String { ... }
    ...
}
struct ContentView: View {

    @StateObject private var appState = AppState()
    @GestureState private var currentState: AppState.LongPressState = .inactive

     
    var body: some View {
        SomeView() 
            .gesture(
                 LongPressGesture() 
                     .updating($currentState) { value, state, transaction in
                         ...
                     }
            )
            .onChange(of: currentState) { appState.currentState = $0 } 
    }
}

注意

我发现动画有点像马车。在该手势上添加onEnded可以修复该手势(DragGesture)。

.onEnded { 
   appState.currentState = .inactive //if you are using DragGesture: .zero (just set to it's initial state again)
}