Firestore get array data at index 0 - swift

Below I have some data in firestore.
I have a an array in the _geoloc field. Each of those indexes have latitude and longitude coordinates. So using SWIFT I want to be able to only get the lat and lng coordinates at index 0 and pass them to individually to a string. I have been researching for days and I am stuck. I have tried to create a new array of strings or an AnyObject array and I just get stuck with retrieving the data I need at index 0, and passing only those 2 lat/lng coordinates to string values. I have several failed snippets of code I could post.
Here is a snippet of what I was attempting to do: (I am really new to firebase so the code is a bit ugly as I am just trying to figure this out)
Firestore.firestore().collection("users").document("626").getDocument { (document, error) in
if let document = document {
// let geo_array = document["_geoloc"]
var yourArray = [String]()
// let geo_location = [geo_array] as [AnyObject]
let array: [Any] = document["_geoloc"] as! [Any]
let tmpArray = array.map({ return String(describing: $0)})
let string = tmpArray.joined(separator: ",")
yourArray.append(string)
print(yourArray[0])

You just need to cast your object from Any to an array of dictionaries and get the first property:
Firestore.firestore().collection("users").document("626").getDocument { document, error in
if let document = document {
var yourArray: [String] = []
if let location = (document["_geoloc"] as? [[String:Double]])?.first,
let latitude = location["lat"],
let longitude = location["lon"] {
let coordinate2d = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
yourArray.append("Latitude: \(location.latitude), Longitude: \(location.Longitude)")
}
}
}

Maybe first declare this:
var firstPositionValues = [AnyObject]()
Then get it like this:
let db = Firestore.firestore().collection("users").document("626")
db.getDocument { (document, error) in
if let document = document {
let geo_location = document["_geoloc"] as [AnyObject] // <- this is all of them in the document
var initialValues = geo_location[0] // <- here are your lat and lng at position 0
self.firstPositionValues = initialValues
}
Hope I understood correctly good luck.

Related

Returning Asynchronous function then assigning a value swift

I'm attempting to return the value of an array and then assign its value to a variable, however when doing so, it returns a blank array. I'm assuming this is due to my lack of knowledge on how to use async in swift so was hoping someone could show me how to do so for this segment of code:
func assignWeights(){
var weightedList = [GMUWeightedLatLng]()
getCoords { coords in
self.coords = coords
for coord in coords {
let lat = Double(coords.location.latitude)!
let long = Double(coords.location.longitude)!
let coordinates = GMUWeightedLatLng(coordinate: CLLocationCoordinate2DMake(lat,long), intensity: 2.0)
weightedList.append(coordinates)
}
print(weightedList) //Array prints contents
}
print(weightedList) //Empty array
heatmapLayer.weightedData = weightedList //Sets to empty array [] as this is ran before getCoords{
}

How to get an array from Firestore document on Swift 5?

Please help me understand the logic reading data from the Firestore document, if one of the values is an array. I tried other answers here and sources but never came to a simple working way and understand clearly. Firestore document structure — example. And Swift class targets for saving (conditional):
struct MyStruct {
var name: String
var pages: Int
}
let part1 = [MyStruct]()
let name1 = ""
let pages1 = 0
let part2 = [MyStruct]()
let name2 = ""
let pages2 = 0
func readFirestore() { }
What should the document reader function look like to add data to existing targets in the class? Thanks in advance for any help in improving my understanding!
They helped to deal with familiar, thank you for what they are. As expected, everything is simple. But for the beginner there is nothing more difficult than simplicity 😁
func readFirestore() {
self.db.collection("example").document("book").getDocument { (document, error) in
if error == nil {
if document != nil && document!.exists {
//get all document data
guard let documentData = document!.data() else {return}
//get value-array for key "part1"
let element = documentData["part1"] as? [Any] //print -> Optional([name1, 100])
//get first element in array
guard let nameDB = element?[0] as? String else {return} //print -> name1
guard let pagesDB = element?[1] as? String else {return} //print -> 100
//append in class
part1.append(MyStruct(name: nameDB, pages: pagesDB))
name1 = nameDB
pages1 = pagesDB
}
}
}
}

convert string to array of cllocationcoordinate2d swift

I am using an API that returns a String that contains coordinate. How do I convert this response:
"route_pins":
"#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"
into an Array of CLLocationCoordinate2D to draw a line using MapKit using:
let polyLine = MKPolyline(coordinates: Locations , count: Locations.count)
busMapView.add(polyLine)
You can do it with a combination of components(separatedBy and map
Split the string by character # and drop the first (empty) item.
Map each item to CLLocationCoordinate2D by splitting the string by the comma, convert the strings to CLLocationCoordinate2D and create the coordinate.
let routePins = "#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"
let coordinates = routePins.components(separatedBy: "#").dropFirst().map { (pin) -> CLLocationCoordinate2D in
let latLng = pin.components(separatedBy: ",").map{ CLLocationDegrees($0)! }
return CLLocationCoordinate2D(latitude: latLng[0], longitude: latLng[1])
}
The result is [CLLocationCoordinate2D].
let dic:Dictionary<String,Any> = ["route_pins": "#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"]
let strLatLng = dic["route_pins"] as! String
let arrayOflatLng = strLatLng.components(separatedBy: "#")
var testcoords = [CLLocationCoordinate2D]()
for latLngStr in arrayOflatLng {
if let strLat = latLngStr.components(separatedBy: ",") as? [String], strLat.count == 2 {
testcoords.append(CLLocationCoordinate2D(latitude: CLLocationDegrees(strLat[0])!, longitude: CLLocationDegrees(strLat[1])!))
}
}
print("testcoords \(testcoords.count)")
let polyLine = MKPolyline(coordinates: testcoords , count: testcoords.count)
busMapView.add(polyLine)
The API string is parsed using 2 levels of parsing ,first we split the API string to locations strings , then using for loop to split each location to its coordinates and save coordinates to CLLocationCoordinate2D and append it to result array
let routePins = "#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"
let pins = routePins.components(separatedBy: "#")//first step is splitting the fetched array to pins array
var LocationsArray = [CLLocationCoordinate2D]()//this is the result array
for location in pins {
if(location.contains(",")){//checking that the location is containing lat ,long separtor
let coordinates = location.components(separatedBy: ",")//splitting the location to lat ,long
//safe parsing the string value to double vale for coordinates
let lat = Double(coordinates[0]) ?? 0.0
let long = Double( coordinates[1]) ?? 0.0
LocationsArray.append(CLLocationCoordinate2D(latitude: lat
,longitude: long))// appending new coordinates to locations array
}
}

Swift3 loop dictionary to add value

I m new to programming I just playing around in playground, I am trying to loop in a dictionary to do some calculation and add them into new dictionary however, I can only add one dictionary value back. I am not sure why. Can anymore tell me and point out the point?
var name:String?
var popDict: [String: Array<Double>]?
var FinalDict: [String: Array<Double>]?
var mean: Double?
var elementSideArr: Array<Double>?
var nameArray = ["Olivia": [1,2,2,2,1,2,1,0.0001,0,1,2], "Amber": [52,52,65,66,57,63,62,0.0001,0,0,0]]
var doubleArr = [Double]()
for (key, value) in nameArray{
let thisValue = value
let arrayS = thisValue.prefix(7)
let slice = arrayS[0...6]
let popSideArr = Array(slice)
let average: Double = (popSideArr as NSArray).value(forKeyPath: "#avg.self") as! Double
mean = average
let thatValue = value
let arraySS = thatValue.suffix(3)
let sslice = arraySS[8...10]
elementSideArr = Array(sslice)
elementSideArr?.insert(average, at: 0)
let dict = ["\(key)": elementSideArr!]
for (key,value) in dict{
popDict = dict
}
}
print(popDict!)
["Olivia": [1.5714285714285714, 0.0, 1.0, 2.0]] // It is the only output but it should be 2 items.
Problem is in your inner for loop you are initializing whole new dictionary to popDict also you don't need for loop if you are having single key and value pair with your dictionary.
Replace line of codes:
let dict = ["\(key)": elementSideArr!]
for (key,value) in dict{
popDict = dict
}
With:
popDict["\(key)"] = elementSideArr!
Note: No need to cast swift array to NSArray to calculate average you can simply use reduce to get total and then divide the total with array count.
let array = popSideArr as? [Int] ?? []
let res = Double(array.reduce(0, +)) / Double(popSideArr.count)

Access snapshot data get from firebase database

I am developing iOS project which uses Firebase database.
I have a observer to observe new data added to my Firebase database:
rootRef.observeEventType(.childAdded, withBlock: {(snap) in
// I try to access "positions" like this
if let mySnap = snap {
let positions = mySnap.childSnapshot(forPath: "positions").value as? Array
// But the positions is nil
})
The snap received is like this (It is print(snap)):
Optional( Snap (-KWoKFfKZOkFyoLI9at_) {
positions = {
0 = {
x = 80;
y = 212;
};
1 = {
x = 80;
y = "212.5";
};
10 = {
x = 83;
y = 229;
}
};
});
What is the right way to access "positions" data that get from firebase database?
As you have added response of mySnap.childSnapshot(forPath: "positions").value in comment it is type of Array of Dictionary so type cast it to [[String: Any]].
let positions = mySnap.childSnapshot(forPath: "positions").value as? [[String: Any]]