微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SwiftUI ObservableObject创建非数组@Published

如何解决SwiftUI ObservableObject创建非数组@Published

我试图用非数组@Published项目创建一个ObservableObject。但是,我仍然不知道该怎么做。我尝试使用?这样做。但是,当我以Text((details.info?.name)!)之类的方式显示它并返回Thread 1: Swift runtime failure: force unwrapped a nil value时,我不知道问题是什么以及如何解决。是我创建可观察对象类的方法正确吗?

class ShopDetailJSON: ObservableObject {
    
    @Published var info : Info?

    init(){load()}
    
    func load() {

        URLSession.shared.dataTask(with: request) { data,response,error in
            guard let data = data else {
                print("No data in response: \(error?.localizedDescription ?? "UnkNown error").")
                return
            }
            if let decodedShopDetails = try? JSONDecoder().decode(ShopDetail.self,from: data) {
                dispatchQueue.main.async {
                    self.info = decodedShopDetails.info!
                }
            } else {
                print("Invalid response from server")
            }
        }.resume()
    }
    
}
struct Info : Codable,Identifiable {
    let contact : String?
    let name : String?
    var id = UUID()

    enum CodingKeys: String,CodingKey {

        case contact = "contact"
        case name = "name"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        contact = try values.decodeIfPresent(String.self,forKey: .contact)
        name = try values.decodeIfPresent(String.self,forKey: .name)
    }

}
struct ShopDetail : Codable {
    let gallery : [gallery]?
    let info : Info?

    enum CodingKeys: String,CodingKey {

        case gallery = "gallery"
        case info = "info"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        gallery = try values.decodeIfPresent([gallery].self,forKey: .gallery)
        info = try values.decodeIfPresent(Info.self,forKey: .info)
    }

}

示例JSON数据

{

    "gallery": [],"info": {
        "contact": "6012345678","name": "My Salon",}
}

解决方法

这个答案是关于代码中发生的事情的一个猜测,但是,如果JSON数据从不为空(如您在注释中所述),则可能是您试图访问 -yet-updated ShopDetailJSON.info可选属性。

首先,进行一些清理。您不需要init(from:)的自定义实现-在您的情况下,只需遵守Codable就足够了。而且,如果JSON值不是可选的,则无需将它们设置为可选类型:

struct Info: Codable,Identifiable {
    let contact : String
    let name : String
    var id = UUID()
}

struct ShopDetail: Codable {
    let gallery : [Gallery]
    let info : Info
}

然后,当您获取JSON时,您将不需要处理可选内容和强制解包!(无论如何应避免这种情况):

if let decodedShopDetails = try? JSONDecoder().decode(ShopDetail.self,from: data {
    DispatchQueue.main.async {
        self.info = decodedShopDetails.info // no force-unwrap needed
    }
}

在视图中,您需要检查info属性是否不是nil,然后才能访问其元素。

struct ContentView: View {

   @ObservedObject var details: ShopDetailJSON

   var body: some View {
       Group() {

           // on iOS14
           if let info = details.info {
               Text(info.name)
           }

           // pre iOS14
           // if details.info != nil {
           //    Text(details.info!.name)
           // }
       }
       .onAppear {
           self.details.load()
       }
   }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。