I tried to create an ObservableObject with non array @Published item. However, I still don't know how to do so. I tried to use a ? to do so. But when I display it in view like Text((details.info?.name)!), and it return Thread 1: Swift runtime failure: force unwrapped a nil value I don't know what the problem and how to solve. Is it my method of creating observable object class are correct?
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)
}
}
Sample JSON data
{
"gallery": [],
"info": {
"contact": "6012345678",
"name": "My Salon",
}
}
.init(from:)or have a customCodingKey- just conforming toDecodable/Encodable(orCodable) is enough, i.e.struct ShopDetail: Codable { var gallery: [Gallery]?; var info: Info? }... other than that, you're trying to use!on anilvalue you get this error. Why this value is nil is hard to say, since we don't know what the JSON that you're decoding looks like - New DevShopDetail.Infooptional, andShopDetail.gallerycan just be[Gallery]- not an optional array. Also, avoid using!to force unwrap. It's hard to be sure what the error, since you're not showing where the error actually occurs. My guess is that you're trying to accessShopDetailJSON.infobefore it's been loaded, which fails. If so, put a conditional:if let info = details.info { Text(info.name) }- New Dev