Evelyn
Evelyn

Reputation: 186

How to grab location using GeoPoint from Cloud Firestore?

Im having trouble trying to set up my code when initialization the location of my stores using GeoPoint from Cloud Firestore. im getting 2 errors when trying to set up the initializer to be able to process the data I have commented the errors on where the problem is.

the errors are showing in my private init?(documentID: String, dictionary: [String: Any]) { :

'let' cannot appear nested inside another 'var' or 'let' pattern & Expected pattern

Initializer for conditional binding must have Optional type, not 'CLLocationCoordinate2D'

I have been trying to modify my model to have cleaner code so that data processes better and is less buggy and less glitchy, im just struggling with the GeoPoint being set up in this structure.

struct Stores {
    var documentID: String
    var name: String
    var category: String
    var price: Int
    var imageURL: URL
    var description: String
    var location: CLLocationCoordinate2D
    var distanceFromUser: Double
    var rating: Int

//    self.distanceFromUser = (CLLocationManager().location?.distance(from: CLLocation(latitude: location.latitude, longitude: location.longitude)))!
//    print("look here!", self.distanceFromUser)
}

extension Stores: DocumentSerializable {

     init(name: String,
          category: String,
          price: Int,
          description: String,
          rating: Int,
          imageURL: URL,
          location: CLLocationCoordinate2D,
          distanceFromUser: Double) {
       let document = Firestore.firestore().products.document()
       self.init(documentID: document.documentID,
                 name: name,
                 category: category,
                 price: price,
                 imageURL: imageURL,
                 description: description,
                 location: location,
                 distanceFromUser: (CLLocationManager().location?.distance(from: CLLocation(latitude: location.latitude, longitude: location.longitude)))!,
                 rating: rating)
     }

     /// Initializes a stores from a documentID and some data, ostensibly from Firestore.
     private init?(documentID: String, dictionary: [String: Any]) {
        guard let name = dictionary["name"] as? String,
           let category =  dictionary["category"] as? String,
           let price =  dictionary["price"] as? Int,
           let rating = dictionary["rating"] as? Int,
           let description =  dictionary["description"] as? String,
           let imageURLString = dictionary["photoURL"] as? String,

           //ERRORS HERE\\
           let geoPoint = dictionary["location"] as? GeoPoint else { return nil}
           let latitude = geoPoint.latitude,
           let longitude = geoPoint.longitude, // errors: 'let' cannot appear nested inside another 'var' or 'let' pattern & Expected pattern

       guard let location =  CLLocationCoordinate2D(latitude: latitude, longitude: longitude) else { return nil }     // error: Initializer for conditional binding must have Optional type, not 'CLLocationCoordinate2D'
           // ERRORS END \

       guard let imageURL =  URL(string: imageURLString) else { return nil }

       self.init(documentID: documentID,
                 name: name,
                 category: category,
                 price: price,
                 imageURL: imageURL,
                 rating: rating,
                 description: description,
                 location: location)
     }

     init?(document: QueryDocumentSnapshot) {
        self.init(documentID: document.documentID, dictionary: document.data())
     }

     init?(document: DocumentSnapshot) {
        guard let data = document.data() else { return nil }
        self.init(documentID: document.documentID, dictionary: data)
     }

     /// The dictionary representation of the restaurant for uploading to Firestore.
     var documentData: [String: Any] {
        return [
         "name": name,
         "category": category,
         "price": price,
         "imageURL": imageURL.absoluteString,
         "description": description
         "rating": rating,
         "location": location
       ]
     }
}

public protocol DocumentSerializable {

    init?(document: QueryDocumentSnapshot)

    init?(document: DocumentSnapshot)

    var documentID: String { get }

    var documentData: [String: Any] { get }

 }

extension Firestore {
  /// Returns a reference to the top-level stores collection.
    var stores: CollectionReference {
        return self.collection("stores")
    }
}

Upvotes: 0

Views: 507

Answers (1)

klememi
klememi

Reputation: 116

You just forgot to end your long guard expression with else { return nil }. Replace

let geoPoint = dictionary["location"] as? GeoPoint,

With

let geoPoint = dictionary["location"] as? GeoPoint else { return nil }

Then place

let latitude = geoPoint.latitude
let longitude = geoPoint.longitude

below and you should be good to go. Last two assignments can't fail so you can place them in guard statement.

Upvotes: 0

Related Questions