【问题标题】:How to dynamically defined an object inside observable objects in swiftui.?如何在swiftui中动态定义可观察对象内的对象。?
【发布时间】:2021-10-02 20:38:16
【问题描述】:

我是 swiftui 的新手,正在学习它。

我有一种情况,我必须在可观察对象内定义一个对象数组(假设对象是 USER,所以对象数组将是“[USER]”)。 这个可观察对象是一个 ViewModel。在初始化此 ViewModel 的任何其他视图中都有 API 调用。

只有在这个 ViewModel 被初始化之后,我才必须初始化这个 [User] 对象。我必须在 ViewModel 中使用这个 [USER],因为这个对象 [USER] 将被其他视图上的 TextField 修改。

由于几个编译时错误,我无法在 API 调用响应后初始化此 [USER] 对象。

struct User: Identifiable {

   var profileName: String = ""
   var profileId: String = ""   
   var firstname: String = ""
   var lastname: String = ""
}


class ViewModel: ObservableObject {

    @Published var document: Document?

    @Published var users = [User]()
    var idValue: String

    init (idValue: String) {
        idValue = idValue
    }
    
    func getDetails() {
        
        APIService.shared.getDocumentDetails(idValue: idValue) { document in
            DispatchQueue.main.async {
                self.document = document
                
                self.setEndUserValues()
            }
        }
    }
    
    func setEndUserValues() {
        
        var users = [User]()
        
        if let document = document, let subjects = document.subjects {
            ForEach(0..<subjects.count, id: \.self) { index in
                let profile = subjects[index]
                var user = User(id: index)
                
                user.profileName = profile.profileName ?? ""
                user.profileId = profile.profileId ?? ""
                user.firstname = profile.firstname ?? ""
                user.lastname = profile.lastname ?? ""
                users.append(user)

            }

        }
    }

我收到 Type '()' cannot conform to 'View' 错误。另外,响应是非常嵌套的,所以我没有提到更多的属性。请帮助我实现这一目标。

【问题讨论】:

  • ForEach 仅适用于 SwiftUI Views。使用for index in 0..&lt;subjects.count。如果您不告诉我们您遇到了什么错误并且Minimal Reproducible Example 无法帮助您解决问题。
  • 谢谢@loremipsum,只有这个用于索引 0..

标签: swiftui nested observable publish-subscribe


【解决方案1】:

您可能会发现以下代码比您的固定代码工作得更好:

struct User: Identifiable {
    
    var profileName: String
    var id: String // In order to conform to Identifiable, you have to have
                   // a variable named "id"
    var firstName: String // We write Swift variables in camelcase. 
    var lastName: String  // You can even see that these get flagged as a spelling error. 
}

class ViewModel: ObservableObject {
    
    @Published var document: Document?
    
    @Published var users = [User]()
    var idValue: String
    
    init(idValue: String) { // I am not sure of the purpose of initializing the
                            // ViewModel with an "id". You shouldn't have multiple
                            // copies of this in your app.
        self.idValue = idValue
    }
    
    func getDetails() {
        APIService.shared.getDocumentDetails(idValue: idValue) { document in
            DispatchQueue.main.async {
                self.document = document
                
                self.setEndUserValues()
            }
        }
    }
    
    func setEndUserValues() {
        if let document = document, let subjects = document.subjects {
            for subject in subjects { // You have an array of Subjects. Use it directly.

                // This way of initializing creates your User and appends it to the
                // array of Users in one step.
                users.append(User(
                    profileName: subject.profileName,
                    id: subject.profileId,
                    firstName: subject.firstname,
                    lastName: subject.lastname))
            }
        }
    }
}

我想在你的代码中显示一些我在上面修复的问题:

func setEndUserValues() {
    
    var users = [User]() // You are creating a local array here. This is not your
                         // "@Published var users"
    
    if let document = document, let subjects = document.subjects {
        for index in 0..<subjects.count { // This becomes unnecessary when you don't
                                          // need the index.
            let profile = subjects[index] // This becomes unnecessary.
            var user = User(id: index) // According to your User struct, this doesn't
                                       // compile. You don't have an initializer that
                                       // accepts an "id: Int"
            
            user.profileName = profile.profileName ?? ""
            user.profileId = profile.profileId ?? ""
            user.firstname = profile.firstname ?? ""
            user.lastname = profile.lastname ?? ""
            users.append(user) // This is your local array of users. This doesn't
                               // actually go anywhere, and you don't actually
                               // fill your ViewModel.users array
        }
    }
}

【讨论】:

    猜你喜欢
    • 2023-01-10
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多