简体   繁体   中英

Optionals with @ObservedObject and @Published var

I am getting quite mad with unwrapping optionals on a SwiftUI project. The project has (removed extra lines for readability):

struct Report: Decodable {
    var siteId: String = "nosite"

    enum ReportKeys: String, CodingKey { //some keys here
    }

    init(from decoder: Decoder) throws {
        // all the code for remapping json properties to the struct
    }
}

class ReportCaller: NSObject, URLSessionDelegate, ObservableObject {
    @Published var lastReport: Report?

    override init() {
        super.init()
        loadReport()
    }
    
    func loadReport() { 
        // URL session code that finally returns
        self.lastReport =  try! decoder.decode(Report, from: data)
    }

The, in my view, I have

struct ContentView: View {
    @ObservedObject var report = ReportCaller()

Now, to make it working, I must unwrap each line, as below:

Text(report.lastReport?.siteId ?? "")

The struct has defaults, so I would expect to not unwrap anything. I recognize I miss some initialization, but I cannot figure out where I should put it. The @ObservedObject calls a class, it seems not the place where to do it. Because the class publishes an optional Report? , I thought to remove the optional there, but I get another problem:

Property 'self.lastReport' not initialized at super.init call

I can try to make

    override init() {
        self.lastReport = Metar()
        super.init()
        loadReport()
    }

Although the compiler complains the from: is missing, because this is effectively what the init in the struct expects. So, I am getting confused on which should be the best way to manage the problem.

The solution is apparently to extend my own struct and provide a default init

struct Report: Decodable {
    var siteId: String
    enum ReportKeys: String, CodingKey { //some keys here
    }

    init(from decoder: Decoder) throws {
        // all the code for remapping json properties to the struct
    }

    init() {
        self.siteId = "nosite"
    }
}

Try removing ()<\/code> after ReportCaller. I'm using a very similar approach that doesn't with ()<\/code> . The code should look like this, I believe:

struct ContentView: View {
    @ObservedObject var report: ReportCaller

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM