在
檔案GamesViewModel.swift模擬了一個數字游戲 ID 串列,在我的真實應用中通過 Websockets 來:
class GamesViewModel: ObservableObject /*, WebSocketDelegate */ {
@Published var currentGames: [Int] = [2, 3]
@Published var displayedGame: Int = 0
func updateCurrentGames() {
currentGames = currentGames.count == 3 ?
[1, 2, 3, 4] : [2, 5, 7]
}
func updateDisplayedGame() {
displayedGame = currentGames.randomElement() ?? 0
}
}
我的問題是,當單擊“加入隨機游戲”按鈕時,我試圖以編程方式激活ContentView.swift 中的隨機 NavigationLink :
struct ContentView: View {
@StateObject private var vm:GamesViewModel = GamesViewModel()
var body: some View {
NavigationView {
VStack {
List {
ForEach(vm.currentGames, id: \.self) { gameNumber in
NavigationLink(destination: GameView(gameNumber: gameNumber)
/* , isActive: $vm.displayedGame == gameNumber */ ) {
Text("Game #\(gameNumber)")
}
}
}
Button(
action: { vm.updateCurrentGames() },
label: { Text("Update games") }
)
Button(
action: { vm.updateDisplayedGame() },
label: { Text("Join a random game") }
)
}
}
}
}
然而,代碼
ForEach(vm.currentGames, id: \.self) { gameNumber in
NavigationLink(destination: GameView(gameNumber: gameNumber),
isActive: $vm.displayedGame == gameNumber ) {
Text("Game #\(gameNumber)")
}
}
不編譯:
無法將“Bool”型別的值轉換為預期的引數型別“Binding”
當我嘗試更改為(洗掉美元符號)時:
ForEach(vm.currentGames, id: \.self) { gameNumber in
NavigationLink(destination: GameView(gameNumber: gameNumber),
isActive: vm.displayedGame == gameNumber ) {
Text("Game #\(gameNumber)")
}
}
它仍然無法編譯!
甚至可以使用 a 的$內部ForEach嗎?
我的背景關系是,在我的真實應用程式中,Jetty 后端在 PostgreSQL 資料庫中創建了一個新游戲,然后將該新游戲的數字 ID 發送到應用程式。并且應用程式應該顯示該游戲,即以編程方式導航到GameView.swift。
uj5u.com熱心網友回復:
問題是您需要一個Binding<Bool>-- 而不僅僅是一個簡單的布爾條件。添加$為您提供了對displayedGame(即 an Binding<Int?>)的系結,但不是 a Binding<Bool>,這是NavigationLink預期的。
一種解決方案是為您要查找的條件創建自定義系結:
class GamesViewModel: ObservableObject /*, WebSocketDelegate */ {
@Published var currentGames: [Int] = [2, 3]
@Published var displayedGame: Int?
func navigationBindingForGame(gameNumber: Int) -> Binding<Bool> {
.init {
self.displayedGame == gameNumber
} set: { newValue in
self.displayedGame = newValue ? gameNumber : nil
}
}
func updateCurrentGames() {
currentGames = currentGames.count == 3 ? [1, 2, 3, 4] : [2, 5, 7]
}
func updateDisplayedGame() {
displayedGame = currentGames.randomElement() ?? 0
}
}
struct ContentView: View {
@StateObject private var vm:GamesViewModel = GamesViewModel()
var body: some View {
NavigationView {
VStack {
List {
ForEach(vm.currentGames, id: \.self) { gameNumber in
NavigationLink(destination: GameView(gameNumber: gameNumber),
isActive: vm.navigationBindingForGame(gameNumber: gameNumber)
) {
Text("Game #\(gameNumber)")
}
}
}
Button(
action: { vm.updateCurrentGames() },
label: { Text("Update games") }
).padding(4)
Button(
action: { vm.updateDisplayedGame() },
label: { Text("Join a random game") }
).padding(4)
}.navigationBarTitle("Select a game")
}
}
}
我更改displayedGame為 an 是Int?因為我認為從語意上講,0如果沒有顯示的游戲,則將其設為 Optional 而不是設定為更有意義,但是如果需要,可以輕松地將其改回。
uj5u.com熱心網友回復:
你也這樣通過
ForEach(vm.currentGames, id: \.self) { gameNumber in
NavigationLink(destination: GameView(gameNumber: gameNumber),
isActive: .constant(vm.displayedGame == gameNumber)) {
Text("Game #\(gameNumber)")
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/344343.html
標籤:ios 迅速 迅捷 swiftui-navigationlink swiftui-导航视图
下一篇:具有排除規則的反向字串
