SwiftUI发布变量不会触发UI更新

时间:2020-06-28 02:44:19

标签: ios swift xcode swiftui observableobject

我有一个带有导航视图列表的应用程序,以后在应用程序中添加新元素时,该视图不会更新。初始屏幕很好,无论我如何编码,此刻一切都将触发,但除此之外,它仍然保持这种状态。在某个时候,我将我的“ init”方法作为.onappear出现,并且动态元素不会出现,但是当我在应用程序中来回移动时,静态元素会被多次添加,这不再是我的代码了。

在这里,我的内容视图是这样的,我试图将导航视图部分移到具有已发布的var的类中,以防万一,在视觉上可以进行任何更改,也可以进行帮助。

struct ContentView: View {
    
    @ObservedObject var diceViewList = DiceViewList()
    
    var body: some View {
        VStack{
            Text("Diceimator").padding()
            diceViewList.body 
            Text("Luck Selector")
        }
    }
}

和DiceViewList类

import Foundation
import SwiftUI
class DiceViewList: ObservableObject {
    @Published var list = [DiceView]()

    init() {
        list.append(DiceView(objectID: "Generic", name: "Generic dice set"))
        list.append(DiceView(objectID: "Add", name: "Add a new dice set"))
        // This insert is a simulation of what add() does with the same exact values. it does get added properly
        let pos = 1
        let id = 1
        self.list.insert(DiceView(objectID: String(id), dice: Dice(name: String("Dice"), face: 1, amount: 1), name: "Dice"), at: pos)
    }

 var body: some View {
        NavigationView {

            List {
                ForEach(self.list) { dView in
                    NavigationLink(destination: DiceView(objectID: dView.id, dice: dView.dice, name: dView.name)) {
                        HStack {  Text(dView.name) }
                    }
                }
            }
        }
    }
    
    func add(dice: Dice) {
        let pos = list.count - 1
        let id = list.count - 1
        self.list.insert(DiceView(objectID: String(id), dice: dice, name: dice.name), at: pos)
        
    }
}

我正在开发最新的Xcode 11,以防万一

编辑:根据建议编辑了代码,问题完全没有改变

struct ContentView: View {
    
    @ObservedObject var vm: DiceViewList = DiceViewList()
    
    var body: some View {


            NavigationView {
                List(vm.customlist) { dice in
                    NavigationLink(destination: DiceView(dice: dice)) {
                        Text(dice.name)
                    }
                } 


        }
    }
}

DiceViewList

class DiceViewList: ObservableObject {
    
    @Published var customlist: [Dice] = []
    func add(dice: Dice) {
 
        self.customlist.append(dice)

    }
     
    init() {
        customlist.append(Dice(objectID: "0", name: "Generic", face: 1, amount: 1))
        customlist.append(Dice(objectID: "999", name: "AddDice", face: 1, amount: 1))
    }
}

2 个答案:

答案 0 :(得分:1)

SwiftUI是您如何构建UIKit应用程序的范式转变。

想法是将“驱动”视图的数据(即View模型)与View表示关注点分开。

换句话说,如果您有一个显示ParentView列表的ChildView(foo:Foo),则ParentView的视图模型应该是Foo对象的数组-不是ChildView s:

struct Foo { var v: String }

class ParentVM: ObservableObject {
   @Published let foos = [Foo("one"), Foo("two"), Foo("three")]
}

struct ParentView: View {
   @ObservedObject var vm = ParentVM()

   var body: some View {
       List(vm.foos, id: \.self) { foo in 
          ChildView(foo: foo)
       }
   }
}

struct ChildView: View {
   var foo: Foo
   var body = Text("\(foo.v)")
}

因此,在您的情况下,请从Dice中添加添加DiceViewList个对象的逻辑(为了简洁起见,我为您保留特定的逻辑):

class DiceListVM: ObservableObject {
   @Published var dice: [Dice] = []

   func add(dice: Dice) {
      dice.append(dice)
   }
}

struct DiceViewList: View {

   @ObservedObject var vm: DiceListVM = DiceListVM()

   var body: some View {
       NavigationView {
          List(vm.dice) { dice in
             NavigationLink(destination: DiceView(for: dice)) {
                Text(dice.name)
             }
       }
   }
}

如果您需要的数据多于Dice中可用的数据,只需创建一个DiceVM以及所有其他属性,例如.name.diceobjectId

但是要点是:不存储和出售视图。-仅处理数据。

答案 1 :(得分:0)

在进行测试时,我意识到了问题所在。我假设在其他所有类中声明@ObservedObject var vm: DiceViewList = DiceViewList()并在需要它的结构中声明它们会找到相同的对象,但事实并非如此!我试图将观察到的对象作为参数传递给包含“添加”按钮的子视图,现在它可以按预期工作。