Cannot read CLLocationDegrees from plist - ios

I am having some trouble with this following struct:
struct EmployeeDetails {
let functionary: String
let imageFace: String
let phone: String
let latitude: CLLocationDegrees
let longitude: CLLocationDegrees
init(dictionary: [String: Any]) {
self.functionary = (dictionary["Functionary"] as? String) ?? ""
self.imageFace = (dictionary["ImageFace"] as? String) ?? ""
self.phone = (dictionary["Phone"] as? String) ?? ""
self.latitude = (dictionary["Latitude"] as! CLLocationDegrees)
self.longitude = (dictionary["Longitude"] as! CLLocationDegrees)
I have no compiling errors but, when I run the app, I get this runtime error:
It's important to say that I am loading data from a plist. Anyone could show me what am I doing wrong?
EDIT:
Now I am having these errors:

The error is pretty clear: you are casting a string-typed value to a NSNumber.
Try this instead:
let latitudeStr = dictionary["Latitude"] as! String
self.latitude = CLLocationDegrees(latitudeStr)!
and you should do the same thing to the "Longitude" property as well ;)
You also may be running into localized numbers issues. Try this:
let numberFormatter = NumberFormatter()
numberFormatter.decimalSeparator = ","
numberFormatter.thousandSeparator = "."
...
self.latitude = numberFormatter.number(from: latitudeStr)!.doubleValue

Related

Ambiguous use of 'subscript' and Cannot call value of non-function type 'AnyObject' errors retrieving data from Firebase in SWIFT 4.1

I'm changing the way I'm posting and retrieving firebase CLLocationCoordinated2D, from one post per value to one post with all values, so I found this post and I would like to implement it in my own code. Retrieving data from Firebase and storing as annotations on a map .
Im having the errors mentioned in the title on the constants date, time, latitude, longitude and desc.
I'm still learning Firebase so any explanation will be very helpful. Tis is the function where I get the errors.
func displayAnnotations() {
let ref = Database.database().reference()
ref.child("Sightings").observe(.childAdded, with: { (snapshot) in
let date = (snapshot.value as AnyObject?)!("Date") as! String?
let time = (snapshot.value as AnyObject)!("Time") as! String?
let latitude = (snapshot.value as AnyObject)!("Latitude") as! String?
let longitude = (snapshot.value as AnyObject?)!("Longitude") as! String?
let desc = (snapshot.value as AnyObject?)!("Description") as! String?
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: (Double(latitude!))!, longitude: (Double(longitude!))!)
annotation.title = date
annotation.subtitle = time
self.mapView.addAnnotation(annotation)
})}
and this is the posting function:
func post() {
let date = dateLabel.text
let time = timeLabel.text
let latitude = latitudeLabel.text
let longitude = longitudeLabel.text
let sightingDescription = descriptionLabel.text
let post: [String:String] = ["Date" : date as AnyObject,
"Time" : time as AnyObject,
"Latitude" : latitude as AnyObject,
"Longitude" : longitude as AnyObject,
"Description" : sightingDescription as AnyObject]
var ref: DatabaseReference!
ref = Database.database().reference()
ref.child("Sightings").childByAutoId().setValue(post)
}
Is it just because it's written for a version previous to swift 4.1?
You changed [] to ()
let dic = snapshot.value as! [String:String]
let date = dic["Date"]
let time = dic["Time"]
let latitude = dic["Latitude"]
let longitude = dic["Longitude"]
let desc = dic["Description"]

Place multiple markers on MKMapView from Firebase Database

I'm creating an iOS app that uses Apple Maps to display markers for Garage/Yard Sales in the local area. So far I've been able to figure out how to place one marker on Apple Maps from the Firebase Database, but I'm not sure how to do it with multiple markers. I've done similar tasks using cells to display different content in a UITableView from Firebase Database but this is my first time doing it map-wise. I was reading an article here that showed how it was possible with JSON data, but due to the fact the marker information will be live, it wouldn't be possible that way for my app. What would be the best way to add multiple markers to a MKMapView?
Snippet from ViewController (Only setup for one marker)
Database.database().reference().child("posts").observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let artwork = Artwork(title: dictionary["title"] as! String,
locationName: dictionary["location"] as! String,
discipline: dictionary["category"] as! String,
coordinate: CLLocationCoordinate2D(latitude: dictionary["lat"] as! Double, longitude: dictionary["long"] as! Double))
self.mapView.addAnnotation(artwork)
}
})
Artwork.swift
class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String
let discipline: String
let coordinate: CLLocationCoordinate2D
init(title: String, locationName: String, discipline: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.locationName = locationName
self.discipline = discipline
self.coordinate = coordinate
super.init()
}
var subtitle: String? {
return locationName
}
}
I was able to figure out a way to this thanks to the link #kosuke-ogawa posted.
Snippet within ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
let ref = Database.database().reference()
let postsRef = ref.child("posts")
postsRef.observeSingleEvent(of: .value, with: { (snapshot) in
for snap in snapshot.children {
let postSnap = snap as! DataSnapshot
if let dict = postSnap.value as? [String:AnyObject] {
let title = dict["title"] as! String
let locationName = dict["location"] as! String
let discipline = dict["category"] as! String
let coordinate = CLLocationCoordinate2D(latitude: dict["lat"] as! Double, longitude: dict["long"] as! Double)
let artwork = Artwork(title: title, locationName: locationName, discipline: discipline, coordinate: coordinate)
self.mapView.addAnnotation(artwork)
}
}
})
}
If there is a cleaner way to do this feel free to edit my code to help others in the future.
for multiple place marker on MKMapView you can take array of ArtWork That you Have created, please try this bellow solution
var arrArtworks: [Artwork] = []
override func viewDidLoad() {
super.viewDidLoad()
intializeData()
PlaceMarker()
}
func intializeData(){
Database.database().reference().child("posts").observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let artwork = Artwork(title: dictionary["title"] as! String,
locationName: dictionary["location"] as! String,
discipline: dictionary["category"] as! String,
coordinate: CLLocationCoordinate2D(latitude: dictionary["lat"] as! Double, longitude: dictionary["long"] as! Double))
arrArtworks.append(Artwork)
}
})
}
func PlaceMarker() {
mapView.addAnnotations(arrArtworks)
}
For example, you can use for loop:
Database.database().reference().child("posts").observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
if let dictionary = child.value as? [String: AnyObject] {
let artwork = Artwork(title: dictionary["title"] as! String,
locationName: dictionary["location"] as! String,
discipline: dictionary["category"] as! String,
coordinate: CLLocationCoordinate2D(latitude: dictionary["lat"] as! Double, longitude: dictionary["long"] as! Double))
self.mapView.addAnnotation(artwork)
}
}
})
cf. http://takeip.com/swift-3-firebase-to-mapkit.html

include local on map with firebase swift - error

I am encountering great difficulties in putting an integrated map based on firebase in my project, I am looking for expert knowledge to help me, even though I build run correctly at the time of running the system for, my code below:
Thanks
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let locationsRef = Database.database().reference(withPath: "locations")
locationsRef.observe(.value, with: { snapshot in
for item in snapshot.children {
guard let locationData = item as? DataSnapshot else { continue }
var locationValue = locationData.value as! [String: Any]
var location: CLLocationCoordinate2D!
if let lat = locationValue["lat"] as? String {
let lng = Double(locationValue["lng"] as! String)!
location = CLLocationCoordinate2D(latitude: Double(lat)!, longitude: lng)
} else {
let lat = locationValue["lat"] as! Double
let lng = locationValue["lng"] as! Double
location = CLLocationCoordinate2D(latitude: lat, longitude: lng)
}
func addAnnotations(coords: [CLLocation]){
for coord in coords{
let CLLCoordType = CLLocationCoordinate2D(latitude: coord.coordinate.latitude,
longitude: coord.coordinate.longitude);
let anno = MKPointAnnotation();
anno.coordinate = CLLCoordType;
self.mapView.addAnnotation(anno);
}
}
}
})
}

How to convert String to CLLocationDegrees Swift 2

I am trying to convert a String that I am retrieving from Firebase and adding it as several annotations on Google Maps. Unfortuanately, my app is crashing whenever it goes through the current code:
ref = FIRDatabase.database().reference()
ref.child("Locations").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
let lat = (snapshot.value!["Latitude"] as! NSString).doubleValue
let lon = (snapshot.value!["Longitude"] as! NSString).doubleValue
let complainLoc = CLLocationCoordinate2DMake(lat, lon)
let Coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
})
My JSON Tree
My Code Block Which Crashes
Here is the code I used for saving data to Firebase
FIRDatabase.database().reference().child("Location").child(FIRAuth.auth()!.currentUser!.uid).setValue(["Latitude": locationManager.location!.coordinate.latitude, "Longitude": locationManager.location!.coordinate.longitude])
SWIFT 5
let dbLat = Double(latStr) // Convert String to double
let dbLong = Double(longStr)
Use latitude and longitude
let center = CLLocationCoordinate2D(latitude: dbLat! , longitude: dbLong! )
let pointAnnotation = MKPointAnnotation()
pointAnnotation.coordinate = CLLocationCoordinate2D(latitude: dbLat!, longitude:dbLong!)
Make sure when you are saving the values of lat and lon to the database you are saving them as Float or Double..
For retrieving use :
ref = FIRDatabase.database().reference()
ref.child("Locations").observeEventType(.Value, withBlock: { (snapshot) in
if snapshot.exists(){
if let locationDictionary = snapshot.value as [String : AnyObject]{
for each in locationDictionary{
//each will bring you every location dictionary in your database for your every user
let lat = each.value!["Latitude"] as! CLLocationDegrees
let lon = each.value!["Longitude"] as! CLLocationDegrees
let userId = each.key as! String
let complainLoc = CLLocationCoordinate2DMake(lat, lon)
let Coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
//Every time this for loop complete's itself it will generate a new set of Coordinates for each user
}
}
}
})
EDIT:
Updated code for Firebase 6 and Swift 5
let ref = self.ref.child("Locations")
ref.observeSingleEvent(of: .value, with: { snapshot in
let allLocations = snapshot.children.allObjects as! [DataSnapshot]
for location in allLocations {
let lat = location.childSnapshot(forPath: "Latitude").value as! CLLocationDegrees
let lon = location.childSnapshot(forPath: "Longitude").value as! CLLocationDegrees
let userId = location.key
let locCoord = CLLocationCoordinate2DMake(lat, lon)
let coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
}
})
note that self.ref points to my Firebase root ref.

Could not cast value of type 'NSTaggedPointerString' to 'NSArray in Google Place Api

i integrated Google Place Api to fetch user location, i have to fetch "area","state" and "City" while i try to get value my App gets crash. Please post ur answer
here my sample code
func mapView(mapView: GMSMapView, idleAtCameraPosition position: GMSCameraPosition)
{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let centerLocation = CLLocation(latitude: position.target.latitude, longitude: position.target.longitude)
CLGeocoder().reverseGeocodeLocation(centerLocation, completionHandler:
{(placemarks, error) in
if (error == nil && placemarks!.count>0)
{
let placemark = CLPlacemark(placemark: placemarksArray[0] as! CLPlacemark)
let latitude = String(format: "%.8f",position.target.latitude)
let longitude = String(format: "%.8f",position.target.longitude)
if let addrList = placemark.addressDictionary
{
print("address==\(address)")
let addStr = address?["FormattedAddressLines"] as! [String]
let addStr1 = address?["City"] as! [String]
let addStr2 = address?["State"] as! [String]
let addStr3 = address?["SubLocality"] as! [String]
NSLog("%#\n%#\n%#", addStr1,addStr2,addStr3)
self.addressLabel.text = addStr.joinWithSeparator(",")
}
}
})
})
}
my output :
address=={
City = "New Delhi";
Country = India;
CountryCode = IN;
FormattedAddressLines = (
"Mayur Vihar",
"New Delhi",
"Delhi 110092",
India
);
Name = 110092;
State = Delhi;
SubAdministrativeArea = Delhi;
SubLocality = "Mayur Vihar";
ZIP = 110092;
}
and my Crash Report :
Could not cast value of type 'NSTaggedPointerString' (0x1064cb860) to 'NSArray' (0x1064cb900).
City and State has String value and FormattedAddressLines has Arry.
Use like this
let addStr1 = address["City"] as! String
let addStr2 = address["State"] as! String
let FormattedAddressLines = address["FormattedAddressLines"] as![String]

Resources