I'm trying to figure out if there is any shorter syntax in Swift for the last line here:
var startPosition: CLLocationCoordinate2D?
var latitude: Double?
var longitude: Double?
// ...
// Here I have skipped some code which may or may not assign values
// to "latitude" and "longitude".
// ...
if latitude != nil && longitude != nil {
startPosition = CLLocationCoordinate2DMake(latitude!, longitude!)
}
As you can see, I want to set the "startPosition" based on "latitude" and "longitude", if those values have been assigned. Otherwise, I accept that the "startPosition" will not be initialized.
I guess this must be possible with "if let" or something similar, but I have failed to figure out how. (I'm experienced in Objective-C, but have just started to learn Swift.)
This is not shorter, but you can simply do
if let latitude = latitude, let longitude = longitude {
startPosition = CLLocationCoordinate2D(latitude: latitude,
longitude: longitude)
}
Notice I used just CLLocationCoordinate2D, not CLLocationCoordinate2DMake. Swift provides constructors without the "make" to most common objects, so you shouldn't usually have to use "make" in constructors.
If you don't want to execute any code after if they are nil use a guard.
var startPosition: CLLocationCoordinate2D?
var latitude: Double?
var longitude: Double?
guard let latitude = latitude && longitude = longitude else {
return
}
startPosition = CLLocationCoordinate2DMake(latitude, longitude)
Clear way
if let latitude = latitude, longitude = longitude {
startPosition = CLLocationCoordinate2D(latitude: latitude,
longitude: longitude)
}
CLLocationCoordinate2D is a struct, it's better if you use the struct initializer. Notice there is only one "let" needed in the if statement.
If i understood the question correctly, you could say
var startPosition: CLLocationCoordinate2D?
var latitude: Double?
var longitude: Double?
if latitude != nil && longitude != nil {
startPosition = CLLocationCoordinate2DMake(latitude!, longitude!)
} else {
startPosition = nil
}
Related
I want to retrieve the longitute and latitude using an address as a string. I found this very useful post here: Convert address to coordinates swift
But when I want to save the results in a double field and return it I can't. What I have done is
func getLatitude(address:String) -> Double{
var lati = 0.0
var geocoder = CLGeocoder()
geocoder.geocodeAddressString("your address") {
placemarks, error in
let placemark = placemarks?.first
if let lat = placemark?.location?.coordinate.latitude{
lati = lat
}
}
}
return lati
}
Inside the geocoder.geocodeAddressString block the value is populated but when I try to return it always gives me 0.0 and I have tried everything. Any ideas please?
If it try to print the value inside the inner block of code it gets printed but I can never return it.
Thank you in advance for the answers.
CLLocationCoordinate2D is struct of latitude and longitude both defined as CLLocationDegrees which itself is a typealias of Double.
var latitude: Double?
var longitude: Double?
func getLocation(address: String) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { placemarks, error in
guard let placemark = placemarks?.first else { return }
let coordinate = placemark.location?.coordinate
latitude = coordinate?.latitude
longitude = coordinate?.longitude
}
}
My map annotation works well when physically putting the numbers in, but, how do I use it so,
for example, latitudelabel.text is read as the latitude rather than 38.897957?
Here is the code:
func showEmergenyOnMap() {
let emergency = MKPointAnnotation()
emergency.title = "Ongoing Emergency"
emergency.coordinate = CLLocationCoordinate2D(latitude: 38.897957, longitude: -77.036560)
Map.addAnnotation(emergency)
}
Covert string to double.
let lati = Double(label.text)
// do same for longi
Then init coordinate
let coords = CLLocationCoordinate2D(latitude: lati, longitude: longi)
UILabel's text property is an Optional variable so it can have a value or a nil. First of all you need to safely unwrap that value because CLLocationDegrees initializer takes a non-optional String. You can see the below example on how to convert labels text to CLLocationCoordinate2D,
var latitude: CLLocationDegrees = 0.0
var longitude: CLLocationDegrees = 0.0
if let latText = latitudelabel.text, let lat = CLLocationDegrees(latText) {
latitude = lat
}
if let longText = longitudelabel.text, let long = CLLocationDegrees(longText) {
longitude = long
}
let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
How can i sort the array based on distance from current location and show in tableview .when i use sorting am not getting any proper results ,am getting the array with random distance.can any one guide me for solve this issue
To sort locations based on distance from current location in best possible way would be have location points in form of struct
struct LocationPoints {
var latitude: CLLocationDegrees
var longitude: CLLocationDegrees
func distance(to currentLocation: CLLocation) -> CLLocationDistance {
return CLLocation(latitude: self.latitude, longitude: self.longitude).distance(from: currentLocation)
}
}
Let suppose you have an array of LocationPoints having latitude & longitude
var coordinates: [LocationPoints] = []
coordinates.append(LocationPoints(latitude: Double(25), longitude: Double(24)))
coordinates.append( LocationPoints(latitude: Double(23), longitude: Double(22)))
sort function
coordinates = sortLocationsWithCurrentLocation(locations: coordinates, currentLocation: CLLocation(latitude: Double(20), longitude: Double(21)))
func sortLocationsWithCurrentLocation(locations:[LocationPoints],currentLocation:CLLocation) -> [LocationPoints] {
//set here current position as current location
let currentPosition : CLLocation = CLLocation(latitude: 30, longitude: 24)
let sortedLocations = locations.sorted(by: { (point1 : LocationPoints, point2 :LocationPoints) -> Bool in
if point1.distance(to: currentPosition) < point2.distance(to: currentPosition)
{
return true
}
return false
})
return sortedLocations
}
Is it possible to convert a string to a longitude/latitude value? I managed to convert the coordinate to a string, but I cannot find a way to revert the process
Another way to convert:
let latitude = (latitudeString as NSString).doubleValue
let longitude = (longitudeString as NSString).doubleValue
Swift 3
let lat = Double(String1)
let lon = Double(String2)
let coordinates = CLLocationCoordinate2D(latitude:lat!
, longitude:lon!)
CLLocationCoordinate2D is a double value it can convert string into double See in above example
My bad, it was a simple type. If anyone ever struggle on how to convert a string to coordinates, here's the correct syntax :
let location:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: Double(([longitudeString] as NSString).doubleValue), longitude: Double(([LatitudeString] as NSString).doubleValue))
var currentLocationLatitude = "45.5626" // your string latitude
var currentLocationLongitude = "45.5626" // your string longitude
var currentLocation:CLLocationCoordinate2D! //location object
currentLocation = CLLocationCoordinate2D(latitude:currentLocationLatitude.toDouble() ?? 0.0, longitude: currentLocationLongitude.toDouble() ?? 0.0)
extension String
{
/// EZSE: Converts String to Double
public func toDouble() -> Double?
{
if let num = NumberFormatter().number(from: self) {
return num.doubleValue
} else {
return nil
}
}
}
You can take string latitude and longitude from you API response and in CLLocationCoordinate2D variable, pass with converting to Double value.
I have also added extension for converting string to double.
might help
let Latitude = ("41" as NSString).doubleValue
let Longitude = ("29" as NSString).doubleValue
I'm trying to build my first Swift application. In this application I'm looping over an KML file that contains information about some restaurant and for each one of them I'm trying to build a Place object with the available information, compare a distance and keep the Place which is the closest to a given point.
Here is my Place model, a very simple model (Place.swift):
import Foundation
import MapKit
class Place {
var name:String
var description:String? = nil
var location:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude:0, longitude:0)
init(name: String, description: String?, latitude: Double, longitude: Double)
{
self.name = name
self.description = description
self.location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
func getDistance(point: CLLocationCoordinate2D) -> Float
{
return Geo.distance(point, coordTo: self.location)
}
}
and here is the part of the application that is looping over the items from the KML file.
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
let xml = SWXMLHash.parse(data);
var minDistance:Float = Float(UInt64.max)
var closestPlace:Place? = nil
var place:Place? = nil
for placemark in xml["kml"]["Document"]["Folder"]["Placemark"] {
var coord = placemark["Point"]["coordinates"].element?.text?.componentsSeparatedByString(",")
// Create a place object if the place has a name
if let placeName = placemark["name"].element?.text {
NSLog("Place name defined, object created")
// Overwrite the place variable with a new object
place = Place(name: placeName, description: placemark["description"].element?.text, latitude: (coord![1] as NSString).doubleValue, longitude: (coord![0] as NSString).doubleValue)
var distance = place!.getDistance(self.middlePosition)
if distance < minDistance {
minDistance = distance
closestPlace = place
} else {
NSLog("Place name could not be found, skipped")
}
}
}
I added breakpoints in this script, when the distance is calculated. The value of the place variable is nil and I don't understand why. If I replace this line:
place = Place(name: placeName, description: placemark["description"].element?.text, latitude: (coord![1] as NSString).doubleValue, longitude: (coord![0] as NSString).doubleValue)
by this line:
let place = Place(name: placeName, description: placemark["description"].element?.text, latitude: (coord![1] as NSString).doubleValue, longitude: (coord![0] as NSString).doubleValue)
I can see that my place object is instantiated correctly now but I can't understand why.
Also I have the exact same issue when I tried to save the closest place:
closestPlace = place
In the inspector the value of closestPlace is nil even after being set with my place object.
I fixed my issue adding a ! after the Place object. I guess is to tell that I am sure I have an Object in this variable and that is not nil.
if let placeName = placemark["name"].element?.text {
NSLog("Place name defined, object created")
// Overwrite the place variable with a new object
place = Place(name: placeName, description: placemark["description"].element?.text, latitude: (coord![1] as NSString).doubleValue, longitude: (coord![0] as NSString).doubleValue)
var distance = place!.getDistance(self.middlePosition)
if distance < minDistance {
minDistance = distance
closestPlace = place!
} else {
NSLog("Place name could not be found, skipped")
}
}