【问题标题】:Updating Lists in SwiftUI after property changes属性更改后在 SwiftUI 中更新列表
【发布时间】:2020-11-20 08:58:52
【问题描述】:

我的程序有两个主要类,TeamPlayer。 Team 有一个内置数组,其中包含 Player 类的 23 个实例,所有实例都有自己的属性和方法。在我的应用程序的主要内容视图中,我显示了这些 homeTeam.players 的列表,并且每一行都有一个 .contextMenu 可以选择调用 editName() 来自单个玩家。

editName() 被调用时,它将打开一个警报并允许用户在 textField 中输入一个新名称,然后保存它并更改 Player 的 name 属性。

我的问题是列表不会在主视图上更新并且玩家名称保持不变,但是当您再次更改它时,名称就在 textField 中,所以它已经改变了,只是'没有被显示。

玩家等级:

    class Player{
        var playerName: String = ""
        var id = UUID()

        init(playerName: String){
             self.playerName = playerName
        }

        func editName{
            //Displays alert with text field
            self.playerName = newName
        }
    }

团队班:

    class Team{
        var teamName: String = ""
        var players: [Player] = [Player("Player 1"),
                                 Player("Player 2"),
                                 Player("Player 3"),
                                 Player("Player 4")] //Continues for 23 Players

        init(teamName: String){
             self.teamName = teamName
        }

    }

快速视图:

    List(homeTeam.players) {player in
        HStack{
            Text("\(player.shirtNumber) - \(player.playerName)")
            Spacer()
            Text("\(player.timerText)")
        }
        .contextMenu{
            Button(action: {player.editName()}) {
                Text("Edit Name")
                Image(systemName: "square.and.pencil")
            }                    
        }
    }

我对 SwiftUI 还是比较陌生,但对 UIKit 和故事板有一定的经验,因此我们将不胜感激。

【问题讨论】:

  • 使您的模型结构并添加视图模型作为 ObservableObject 持有您的模型作为发布的属性。
  • 将播放器类更改为结构?团队也是?然后我将什么更改为 ObservableObject?抱歉,这方面经验不是很丰富

标签: ios swift list swiftui


【解决方案1】:

这是可能的方式(未测试,内联输入)

struct Player: Identifiable {
    var playerName: String = ""
    var id = UUID()

    init(playerName: String){
         self.playerName = playerName
    }

    mutable func editName{
        //Displays alert with text field
        self.playerName = newName
    }
}

struct Team{
    var teamName: String = ""
    var players: [Player] = [Player("Player 1"),
                             Player("Player 2"),
                             Player("Player 3"),
                             Player("Player 4")] //Continues for 23 Players

    init(teamName: String){
         self.teamName = teamName
    }
}

现在将模型视为

class ViewModel: ObservableObject {
   @Published var homeTeam = Team()
}

and updated view

struct ContentView: View {
   @StateObject var vm = ViewModel()

   var body: some View {
    List(Array(vm.homeTeam.players.enumerated()), id: \.1) { (index, player) in
        HStack{
            Text("\(player.shirtNumber) - \(player.playerName)")
            Spacer()
            Text("\(player.timerText)")
        }
        .contextMenu{
            Button(action: {vm.homeTeam.players[i].editName()}) {
                Text("Edit Name")
                Image(systemName: "square.and.pencil")
            }                    
        }
    }
   }
}

【讨论】:

  • 在一个空视图上测试它,它就像我想要的那样工作;当我尝试将它实施到我的项目中时,我在此代码上收到错误“转义闭包捕获变异'self'参数”:let enter = UIAlertAction(title: "Enter", style: .default) { (_) in self.playerName = alert.textFields![0].text! }任何想法?
  • 你应该只通过视图模型更新模型,因为模型现在是值类型。
  • 您如何建议让用户输入一个新名称,而不像我目前使用的那样使用 textView 和警报?
【解决方案2】:
  • 将 Team 的一致性添加到 ObservableObject
  • 确保 homeTeam 标记为 @ObservedObject var homeTeam: Team
  • 当需要编辑玩家的名字时,调用一个(新的)方法 Team,而不是 Player,可能命名为 changeName(player: Player, to newName: String) 为您进行更改
  • 确保 changeName() 调用 Team 方法 objectWillChange.send() 所以视图知道团队已经改变 (此方法是 ObservedObject 协议的一部分)。就是这样 导致视图重绘。

来自 HackingWithSwift (@delawaremathguy) 的回答 - https://www.hackingwithswift.com/forums/swiftui/updating-lists-in-swiftui-after-property-changes/4910

【讨论】:

    猜你喜欢
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 2020-11-15
    相关资源
    最近更新 更多