我想把三个链接放在一个NavigationView中。
"room.A"
下面的代码无法工作,因为SwiftUI在构建NavigationView时调用UUID()NavigationView并重用它。
当用户单击链接时,我想生成一个新的随机房间ID,但我无法弄清楚如何做到这一点。我正在寻找一种简单而自然的方式来实现这一点。
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: RoomView(roomId: "room.A")) {
Text("Enter Room A")
}
NavigationLink(destination: RoomView(roomId: "room.B")) {
Text("Enter Room B")
}
NavigationLink(destination: RoomView(roomId: UUID().uuidString)) {
Text("Create a new Room and enter")
}
}
}
}
}
struct RoomView: View {
let roomId: String
var body: some View {
Text("Room View \(roomId)")
}
}发布于 2021-04-22 15:14:26
我找到了一个简单的解决方案,但这暴露了SwiftUI的怪异之处。这段代码和上面的代码在逻辑上是相同的,但是由于SwiftUI的优化,它们的行为有所不同。
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: RoomView(roomId: "room.A")) {
Text("Enter Room A")
}
NavigationLink(destination: RoomView(roomId: "room.B")) {
Text("Enter Room B")
}
NavigationLink(destination: NewRoomView()) {
Text("Create a new Room and enter")
}
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct NewRoomView: View {
var body: some View {
RoomView(roomId: UUID().uuidString)
}
}发布于 2021-04-22 14:02:11
这是因为导航链接是急切地执行的。我创建了一个视图,可以在tap上运行创建。
import SwiftUI
struct LazyView<Content>: View where Content: View {
private let viewBuild: () -> Content
fileprivate init(_ viewBuild: @escaping () -> Content) {
self.viewBuild = viewBuild
}
init(_ viewBuild: @escaping @autoclosure () -> Content) {
self.init(viewBuild)
}
var body: some View {
viewBuild()
}
}
extension NavigationLink {
init<V>(lazyDestination: @escaping @autoclosure () -> V, @ViewBuilder label: () -> Label) where Destination == LazyView<V> {
self.init(destination: LazyView(lazyDestination), label: label)
}
init<V>(lazyDestination: @escaping @autoclosure () -> V, isActive: Binding<Bool>, @ViewBuilder label: () -> Label)
where Destination == LazyView<V> {
self.init(destination: LazyView(lazyDestination), isActive: isActive, label: label)
}
init<V, T>(lazyDestination: @escaping @autoclosure () -> V, tag: T, selection: Binding<T?>, @ViewBuilder label: () -> Label)
where T : Hashable, Destination == LazyView<V> {
self.init(destination: LazyView(lazyDestination), tag: tag, selection: selection, label: label)
}
}
extension NavigationLink where Label == Text {
init<V>(_ titleKey: LocalizedStringKey, lazyDestination: @escaping @autoclosure () -> V) where Destination == LazyView<V> {
self.init(titleKey, destination: LazyView(lazyDestination))
}
init<V, S>(_ title: S, lazyDestination: @escaping @autoclosure () -> V) where S : StringProtocol, Destination == LazyView<V> {
self.init(title, destination: LazyView(lazyDestination))
}
init<V>(_ titleKey: LocalizedStringKey, lazyDestination: @escaping @autoclosure () -> V, isActive: Binding<Bool>)
where Destination == LazyView<V> {
self.init(titleKey, destination: LazyView(lazyDestination), isActive: isActive)
}
init<V, S>(_ title: S, lazyDestination: @escaping @autoclosure () -> V, isActive: Binding<Bool>)
where S : StringProtocol, Destination == LazyView<V> {
self.init(title, destination: LazyView(lazyDestination), isActive: isActive)
}
init<V, T>(_ titleKey: LocalizedStringKey, lazyDestination: @escaping @autoclosure () -> V, tag: T, selection: Binding<T?>)
where T : Hashable, Destination == LazyView<V> {
self.init(titleKey, destination: LazyView(lazyDestination), tag: tag, selection: selection)
}
init<V, S, T>(_ title: S, lazyDestination: @escaping @autoclosure () -> V, tag: T, selection: Binding<T?>)
where S : StringProtocol, T : Hashable, Destination == LazyView<V> {
self.init(title, destination: LazyView(lazyDestination), tag: tag, selection: selection)
}
}然后,在您的代码中,用
NavigationLink(lazyDestination: RoomView(roomId: UUID().uuidString)) {
Text("Create a new Room and enter")
}https://stackoverflow.com/questions/67214370
复制相似问题