“带动画”的SwiftUI不适用于“inout”参数

6jjcrrmo  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(114)

我正在编写一个在SwiftUI中模仿macOS侧边栏行为的检查器视图。它只在整个视图出现和消失时使用.transition(.move(edge: .trailing)),但在内部视图之间切换时不使用。

所以我想出了以下代码。Selection是一个枚举表示视图一对一,总是以case none开始。inspect()方法用于改变选择值和确定是否使用动画(记得我提到过不要使用动画时,切换内部视图)。我附上我的完整代码在最后。
但是,永远不会有任何动画应用.我该如何解决这个问题?
如果我在inspect()方法中直接使用@State selection这个更具体的方法,动画会回来,但是如果我有另一个Inspector,比如@State var selection2: Selection2,就不能重用代码。

func inspect(to target: Selection) {
    if target.rawValue == 0 {
        withAnimation {
            selection = target
        }
    } else {
        if selection.rawValue == 0 {
            withAnimation {
                selection = target
            }
        } else {
            selection = target
        }
    }
}

下面是我的完整代码:

struct ContentView: View {
    
    enum Selection: Int {
        case none
        case view1
        case view2
        case view3
    }
    
    @State var selection: Selection = .none
    
    func inspect<Selection: RawRepresentable<Int>>(_ selection: inout Selection, to target: Selection) {
        if target.rawValue == 0 {
            withAnimation {
                selection = target
            }
        } else {
            if selection.rawValue == 0 {
                withAnimation {
                    selection = target
                }
            } else {
                selection = target
            }
        }
    }
    
    var body: some View {
        HStack {
            VStack {
                Button("None") {
                    inspect(&selection, to: .none)
                }
                Button("View 1") {
                    inspect(&selection, to: .view1)
                }
                Button("View 2") {
                    inspect(&selection, to: .view2)
                }
                Button("View 3") {
                    inspect(&selection, to: .view3)
                }
            }
            
            Group {
                if selection.rawValue == 1 {
                    Text("Hello 1")
                } else if selection.rawValue == 2 {
                    Text("Hello 2")
                } else if selection.rawValue == 3 {
                    Text("Hello 3")
                }
            }
            .transition(.move(edge: .trailing))
        }
        
    }
}
n6lpvg4x

n6lpvg4x1#

你的代码看起来有点复杂,所以我已经简化了它,如果我理解你想做什么正确的行为也如预期。
首先,我直接在inspect函数中使用了@State属性,因此不需要将其作为参数传递,而且这里也不需要泛型

func inspect(to target: Selection) {
    if target == .none {
        withAnimation {
            selection = target
        }
    } else {
        if selection == .none {
            withAnimation {
                selection = target
            }
        } else {
            selection = target
        }
    }
}

正如上面所看到的,我直接使用枚举大小写,而不是任何原始值,事实上,我从枚举中删除了原始值

enum Selection {
    case none
    case view1
    case view2
    case view3
}

并因此更改Group中的代码

Group {
    if selection == .view1 {
        Text("Hello 1")
    } else if selection == .view2 {
        Text("Hello 2")
    } else if selection == .view3 {
        Text("Hello 3")
    }
}

总的来说,我认为这使得代码更干净,更容易阅读。

相关问题