Firestore API Call

Hello,

I am still new to Firestore and calling api’s. My response keeps coming up nil. what is the disconnect? I’m using Xcode’s playground. Here is the Swift code:

import SwiftUI


struct DeliveryOffer: Codable {
    let offers: [Offer]
    
    private enum CodingKeys: String, CodingKey {
        case offers = "documents"
    }
  
}

struct Stringvalue: Codable {
    let value: String
    
    private enum CodingKeys: String, CodingKey {
        case value = "Stringvalue"
    }
    
}

struct Doublevalue: Codable {
    let value: Double
    
    private enum CodingKeys: String, CodingKey {
        case value = "Doublevalue"
    }
    
}

struct Offer: Codable {
    let country: String
    let instructions: String
    let longitude: Double
    let street: String
    let brandName: String
    let city: String
    let latitude: Double
    let state: String
    let unit: String
    let postalCode: String
    
    private enum OfferKeys: String, CodingKey {
        case fields
    }
    
    private enum FieldsKeys: String, CodingKey {
        case country
        case instructions
        case longitude
        case street
        case brandName
        case city
        case latitude
        case state
        case unit
        case postalCode
    }
    
    // Create a decoder
    
        // 1. Get the container
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: OfferKeys.self)
            let fieldContainer = try container.nestedContainer(keyedBy: FieldsKeys.self, forKey: .fields)
            country = try fieldContainer.decode(Stringvalue.self, forKey: .country).value
            instructions = try fieldContainer.decode(Stringvalue.self, forKey: .instructions).value
            longitude = try fieldContainer.decode(Doublevalue.self, forKey: .longitude).value
            street = try fieldContainer.decode(Stringvalue.self, forKey: .street).value
            brandName = try fieldContainer.decode(Stringvalue.self, forKey: .brandName).value
            city = try fieldContainer.decode(Stringvalue.self, forKey: .city).value
            latitude = try fieldContainer.decode(Doublevalue.self, forKey: .latitude).value
            state = try fieldContainer.decode(Stringvalue.self, forKey: .state).value
            unit = try fieldContainer.decode(Stringvalue.self, forKey: .unit).value
            postalCode = try fieldContainer.decode(Stringvalue.self, forKey: .postalCode).value
            
        }
    
}

let url = "https://firestore.googleapis.com/v1/projects/goe-dash-llc/databases/(default)/documents/users/trCln2nBPi1oMLBjMJ2Z/pickup"

URLSession.shared.dataTask(with: URL(string: url)!) { (data, _, error) in
    
    guard let data = data, error == nil else {
        fatalError("No data found")
    }

    let response = try? JSONDecoder().decode(DeliveryOffer.self, from: data)
    if let response = response {
        print(response)
    }
    
}.resume()


Here is the JSON tree:

{
    "name": "projects/goe-dash-llc/databases/(default)/documents/users/trCln2nBPi1oMLBjMJ2Z/pickup/8ZVFlTyNHa2lCS1Oyro2",
    "fields": {
        "unit": {
            "stringValue": "3050"
        },
        "street": {
            "stringValue": "St. Daphne Dr."
        },
        "brandName": {
            "stringValue": "brandName"
        },
        "latitude": {
            "nullValue": null
        },
        "postalCode": {
            "stringValue": "63301"
        },
        "instructions": {
            "stringValue": "Hello! I am a text field!"
        },
        "country": {
            "stringValue": "USA"
        },
        "longitude": {
            "nullValue": null
        },
        "city": {
            "stringValue": "St. Charles"
        },
        "state": {
            "stringValue": "MO"
        }
    },
    "createTime": "2022-10-03T17:11:00.845679Z",
    "updateTime": "2022-10-06T02:27:39.913957Z"
}

Use a do catch statement here and catch the error and print it to see what you may be missing when decoding the data

I used a different method as I’m not too family yet with the “do catch”:

let response = try? JSONDecoder().decode(DeliveryOffer.self, from: data)
    if let response = response {
        print(response)
    } else if response == nil {
        print(error!.localizedDescription)
    }

Here is what got printed out: Fatal error: Unexpectedly found nil while unwrapping an Optional value

Would a “do catch” give me something else? If so I’d appreciate the assistance, please.

Hello @Chris_Parker,

Care to take a look at my problem and offer a solution?

Yes it will give you the actual error of what’s happening.

You can read more about do catch statements here it’s all about proper error handling

Also no need to tag Chris Parker or others, it can discourage others from answering your question, because you’re only looking for an answer by a specific person

What error is shown when using this code?

do {
   let response = try JSONDecoder().decode(DeliveryOffer.self, from: data)
   print(response)

} catch {
   print(error)
}

This happened because an error isn’t actually there

Sorry Mikael. I see that I got that same error. Now, how do I fix it? So far I have massaged the code to this one error.

@coder3000

Hi Gilbert,

Set some breakpoints further back in your code before you get to the do, catch block because the error is occurring earlier.

BTW, the name of my colleague in this thread is Mikaela.

2 Likes

How do I output this json into a UITableView:

"fields": {
        "brandName": {
            "stringValue": "brandName"
        },
        "unit": {
            "stringValue": "3050"
        },
        "street": {
            "stringValue": "St. Daphne Dr."
        },
        "postalCode": {
            "stringValue": "63301"
        },
        "city": {
            "stringValue": "St. Charles"
        },
        "state": {
            "stringValue": "MO"
        },
        "country": {
            "stringValue": "USA"
        },
        "instructions": {
            "stringValue": "Hello! I am a text field!"
        }
    }
}

I have this model that works but I can’t get the delegate and datasource to network properly:

// MARK: - DeliveryOffer
struct DeliveryOffer: Codable {
    let fields: Fields
}

// MARK: - Fields
struct Fields: Codable {
    let brandName, unit, street, postalCode, city, state, country, instructions: BusinessInfo
    
}

// MARK: - BrandName
struct BusinessInfo: Codable {
    let stringValue: String
}

please help.

You should make a separate post for this

Will do,