0

It logged something like this " nw_protocol_get_quic_image_block_invoke dlopen libquic failed " but there's a value in it.

When I tried to print it out in a view, it does not work at all What did I do wrong?

class MoneyView:ObservableObject {
    @Published var currency:Rate?
    
    init() {
        fetchData()
        print(self.currency!.CAD) // This does not have any value aka nil
    }
    
    func fetchData() {
        print("Gajellas amat")
        guard let url = URL(string: "http://api.exchangeratesapi.io/v1/latest?access_key=24a5ab7688a7044f60bfeb491eb37550") else {
            return
        }
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: url) {(data, response, error) in
            if error == nil {
                let decoder = JSONDecoder()
                if let safeData = data {
                    do{
                        let result =  try decoder.decode(Root.self, from: safeData)
                        DispatchQueue.main.async {
                            self.currency = result.rates
                            print(result.rates.CAD)
                            print("Ada ada aja -----------")
                            print(self.currency!.CAD) // This has value
                        }
                        
                    } catch {
                        print(error)
                    }
                }
            }
        }
        task.resume()
    }
}

my view :

struct NewDisplay: View {
    @ObservedObject var fetch = MoneyView()
    var body: some View {
        Text(String(self.fetch.currency!.CAD))
        Text("Makan bang")
    }
}
Farhandika
  • 437
  • 1
  • 3
  • 16
  • Does this answer your question? [What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?](https://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – EmilioPelaez May 10 '21 at 13:25
  • Why would it have a value? you are just initiating the `class` and you haven't given it a value. Your `fetchData` is `async` your `print` runs before `fetchData` is done. Also, switch your `ObservedObject` to `StateObject` if you want to [initialize like that](https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app). – lorem ipsum May 10 '21 at 13:29
  • so how do i run the fectData function before the print?? and I already tried to use StateObject, still gave me the same result as before – Farhandika May 10 '21 at 13:49
  • `dataTask` is `async` since it uses a [completion handler](https://developer.apple.com/documentation/foundation/urlsession/1407613-datatask) you can't make it `sync` you will have a `nil` value until `dataTask` is done. The good news is that as soon as the `async` work is done you'll get the correct values. I would put a `ProgressView` on the screen until `currency` is no longer `nil` – lorem ipsum May 10 '21 at 13:57

1 Answers1

1

It's a timing problem. The API call is asynchronous.

Delete the init method

  init() {
    fetchData()
    print(self.currency!.CAD) // This does not have any value aka nil
}  

and fetch the data in onAppear. Replace

struct NewDisplay: View {
    @ObservedObject var fetch = MoneyView()
    var body: some View {
        Text(String(self.fetch.currency!.CAD))
        Text("Makan bang")
    }
}

with

struct NewDisplay: View {
    @StateObject var fetch = MoneyView()
    var body: some View {
        Text(String(self.fetch.currency?.CAD ?? 0.0))
        Text("Makan bang")
    }
    .onAppear {
       fetch.fetchData()
    }
}

@ObservedObject is actually for objects which are not owned by the current view.

The nil-coalescing operator ?? avoids a crash, because the value is not available (yet) when the view is rendered the first time.

Side note:

The message nw_protocol_get_quic_image_block_invoke dlopen libquic failed is irrelevant.

vadian
  • 274,689
  • 30
  • 353
  • 361