SwiftUI嵌套列表在选择之前调用navigationLink。

huangapple go评论91阅读模式
英文:

SwiftUI nested list calls navigationLink prior to selection

问题

我在Swift UI中遇到了一个嵌套列表的问题,似乎每个列表项都会调用其相应的navigationLink,而不管是否被选中并忽略其被禁用的事实,我不确定为什么会发生这种情况。以下是我的代码,大部分的Swift格式已被删除:

struct Team: Identifiable {
    let id = UUID()
    let name: String
    let icon: String
    let teamCode: String
    let showTeam: Bool
    var items: [Team]?
}

struct NFLView: View {
    var userPlayEstimates: UserPlayData
    var userAllRosters: userAllRosters
    
    let items: [Team] = [.AFCNorth, .AFCSouth, .AFCEast, .AFCWest]
    
    var body: some View {
        VStack {
            NavigationStack {
                Image("NFL_Logo")
                    .resizable()
                List(items, children: \.items) { row in
                    NavigationLink {
                        NFLTeamRosterView(teamName: row.name, teamCode: row.teamCode, userAllRosters: userAllRosters)
                    } label: {
                        Text(row.name)
                    }
                    .disabled(!row.showTeam)
                }
            }
        }
    }
}

extension Team {
    static let rai = Team(name: "Raiders", icon: "RAI_Logo", teamCode: "rai", showTeam: true)
    static let rav = Team(name: "Ravens", icon: "BAL_Logo", teamCode: "rav", showTeam: true)
    static let mia = Team(name: "Dolphins", icon: "MIA_Logo", teamCode: "mia", showTeam: true)
    static let buf = Team(name: "Bills", icon: "BUF_Logo", teamCode: "buf", showTeam: true)
    static let nwe = Team(name: "Patriots", icon: "NWE_Logo", teamCode: "nwe", showTeam: true)
    static let nyj = Team(name: "Jets", icon: "NYJ_Logo", teamCode: "nyj", showTeam: true)
    static let cin = Team(name: "Bengals", icon: "CIN_Logo", teamCode: "cin", showTeam: true)
    static let pit = Team(name: "Steelers", icon: "PIT_Logo", teamCode: "pit", showTeam: true)
    static let cle = Team(name: "Browns", icon: "CLE_Logo", teamCode: "cle", showTeam: true)
    static let jax = Team(name: "Jaguars", icon: "JAX_Logo", teamCode: "jax", showTeam: true)
    static let oti = Team(name: "Titans", icon: "OTI_Logo", teamCode: "oti", showTeam: true)
    static let clt = Team(name: "Colts", icon: "CLT_Logo", teamCode: "clt", showTeam: true)
    static let htx = Team(name: "Texans", icon: "HTX_Logo", teamCode: "htx", showTeam: true)
    static let kan = Team(name: "Chiefs", icon: "KAN_Logo", teamCode: "kan", showTeam: true)
    static let sdg = Team(name: "Chargers", icon: "SDG_Logo", teamCode: "sdg", showTeam: true)
    static let den = Team(name: "Broncos", icon: "DEN_Logo", teamCode: "den", showTeam: true)
    
    static let AFCWest = Team(name: "AFC West", icon: "NFL_Logo", teamCode: "AFCW", showTeam: false, items: [Team.rai, Team.kan, Team.sdg, Team.den])
    static let AFCNorth = Team(name: "AFC North", icon: "NFL_Logo", teamCode: "AFCN", showTeam: false, items: [Team.rav, Team.pit, Team.cle, Team.cin])
    static let AFCSouth = Team(name: "AFC South", icon: "NFL_Logo", teamCode: "AFCS", showTeam: false, items: [Team.jax, Team.oti, Team.htx, Team.clt])
    static let AFCEast = Team(name: "AFC East", icon: "NFL_Logo", teamCode: "AFCE", showTeam: false, items: [Team.nwe, Team.mia, Team.nyj, Team.buf])
}

背景信息是,NFLTeamRosterView被设计为接受任何球队,而不是AFC分区的输入,因此被禁用为可选择的列表项。然而,每当我调用这个视图时(特别是我用NFLView(userPlayEstimates: userPlays, userAllRosters: userRosters)显示一个sheet时),我立即从NFLTeamRosterView中得到一个错误-它被调用在我的第一个列表项上-NFLTeamRosterView(teamName: "AFC North", teamCode: "AFCN")

显然,这是一个问题,因为它会导致我必须设计解决这个问题,但这是否意味着每次我创建这个嵌套列表时,每个navigationLink都会被运行?如果是这样的话,这似乎是一个相当大的计算负担,有没有办法防止这种情况发生?

英文:

I am running into an issue with a nested list in Swift UI where it seems that every list item is making a call to its respective navigationLink regardless of being selected and ignoring the fact that it's disabled, and I'm not sure about why this happens. My code is below, with most of the swift formatting removed-

struct Team: Identifiable {
let id = UUID()
let name: String
let icon: String
let teamCode: String
let showTeam: Bool
var items: [Team]?
}
struct NFLView: View {
var userPlayEstimates : UserPlayData
var userAllRosters : userAllRosters
let items: [Team] = [.AFCNorth, .AFCSouth, .AFCEast,.AFCWest]
var body: some View {
VStack{
NavigationStack{
Image("NFL_Logo")
.resizable()
List(items, children: \.items) {row in
NavigationLink{
NFLTeamRosterView(teamName : row.name, teamCode: row.teamCode, userAllRosters : userAllRosters)
} label: {
Text(row.name)
}
.disabled(!row.showTeam)
}
}  
}
}
}
extension Team {
static let rai = Team(name:"Raiders", icon:"RAI_Logo", teamCode:"rai", showTeam:true)
static let rav = Team(name:"Ravens", icon:"BAL_Logo", teamCode:"rav", showTeam:true)
static let mia = Team(name:"Dolphins", icon:"MIA_Logo", teamCode:"mia", showTeam:true)
static let buf = Team(name:"Bills", icon:"BUF_Logo", teamCode:"buf", showTeam:true)
static let nwe = Team(name:"Patriots", icon:"NWE_Logo", teamCode:"nwe", showTeam:true)
static let nyj = Team(name:"Jets", icon:"NYJ_Logo", teamCode:"nyj", showTeam:true)
static let cin = Team(name:"Bengals", icon:"CIN_Logo", teamCode:"cin", showTeam:true)
static let pit = Team(name:"Steelers", icon:"PIT_Logo", teamCode:"pit", showTeam:true)
static let cle = Team(name:"Browns", icon:"CLE_Logo", teamCode:"cle", showTeam:true)
static let jax = Team(name:"Jaguars", icon:"JAX_Logo", teamCode:"jax", showTeam:true)
static let oti = Team(name:"Titans", icon:"OTI_Logo", teamCode:"oti", showTeam:true)
static let clt = Team(name:"Colts", icon:"CLT_Logo", teamCode:"clt", showTeam:true)
static let htx = Team(name:"Texans", icon:"HTX_Logo", teamCode:"htx", showTeam:true)
static let kan = Team(name:"Chiefs", icon:"KAN_Logo", teamCode:"kan", showTeam:true)
static let sdg = Team(name:"Chargers", icon:"SDG_Logo", teamCode:"sdg", showTeam:true)
static let den = Team(name:"Broncos", icon:"DEN_Logo", teamCode:"den", showTeam:true)
static let AFCWest = Team(name: "AFC West", icon: "NFL_Logo", teamCode:"AFCW", showTeam:false, items: [Team.rai, Team.kan, Team.sdg, Team.den])
static let AFCNorth = Team(name: "AFC North", icon: "NFL_Logo", teamCode:"AFCN", showTeam:false, items: [Team.rav, Team.pit, Team.cle, Team.cin])
static let AFCSouth = Team(name: "AFC South", icon: "NFL_Logo", teamCode:"AFCS", showTeam:false, items: [Team.jax, Team.oti, Team.htx, Team.clt])
static let AFCEast = Team(name: "AFC East", icon: "NFL_Logo",  teamCode:"AFCE", showTeam:false, items: [Team.nwe, Team.mia, Team.nyj, Team.buf])
}

For background, NFLTeamRosterView is designed to accept any team, not an AFC division input, thus the reason for it being disabled as a selectable list item. Any time I make a call to this view though (in particular I'm showing a sheet with NFLView(userPlayEstimates: userPlays, userAllRosters: userRosters), I get an immediate error from NFLTeamRosterView- it's being called on my first list item - NFLTeamRosterView(teamName : "AFC North", teamCode : "AFCN")

Obviously this is a problem in that it causes issues I'd have to design around, but does it also mean that any time I'm creating this nested list that every navigationLink is being run? This seems like a pretty big computation drain if so, and is there a way to prevent that from happening?

答案1

得分: 0

这是在SwiftUI中的预期行为。你可以尝试使用if/else来替代禁用链接:

struct NFLView: View {
    var userPlayEstimates: UserPlayData
    var userAllRosters: userAllRosters
    
    let items: [Team] = [.AFCNorth, .AFCSouth, .AFCEast, .AFCWest]
    
    var body: some View {
        VStack {
            NavigationStack {
                Image("NFL_Logo")
                    .resizable()
                List(items, children: \.items) { row in
                    if row.showTeam {
                        NavigationLink {
                            NFLTeamRosterView(teamName: row.name, teamCode: row.teamCode, userAllRosters: userAllRosters)
                        } label: {
                            Text(row.name)
                        }
                    } else {
                        Text(row.name)
                    }
                }
            }
        }
    }
}

希望对你有帮助!

英文:

This is expected behaviour in SwiftUI. You could try using if/else instead of disabling the link:

struct NFLView: View {
var userPlayEstimates : UserPlayData
var userAllRosters : userAllRosters
let items: [Team] = [.AFCNorth, .AFCSouth, .AFCEast,.AFCWest]
var body: some View {
VStack{
NavigationStack{
Image("NFL_Logo")
.resizable()
List(items, children: \.items) { row in
if row.showTeam {
NavigationLink{
NFLTeamRosterView(teamName : row.name, teamCode: row.teamCode, userAllRosters : userAllRosters)
} label: {
Text(row.name)
}
} else {
Text(row.name)
}
}
}  
}
}
}

huangapple
  • 本文由 发表于 2023年8月8日 22:01:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860301.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定