Problem with MapBox PointAnnotations with data from Alamofire - ios

In my app I need to get annotations coordinates from server, so im getting is with Alamofire request. And when I try to add annotations to map from Alamofire pid im getting unknown error
class MapViewController : UIViewController, MGLMapViewDelegate, FloatingPanelControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
....
....
getDataFromServer()
}
func getDataFromServer() {
let coffeeShopsJSON = AF.request("http://194.6*******")
coffeeShopsJSON.responseJSON { response in
switch response.result {
case .success(let value):
let jsonFile = JSON(value)
let arrayCount = jsonFile.array?.count ?? 0
var id = [Int]()
var name = [String]()
var lat = [Double]()
var lon = [Double]()
var img = [UIImage(named : "cofShopIcon"), UIImage(named : "cofShopIcon"), UIImage(named : "cofShopIcon"), UIImage(named : "cofShopIcon"), UIImage(named : "cofShopIcon")] //test images
for i in 0..<arrayCount {
let j_id = jsonFile[i]["id"].string ?? "-1"
id.append(Int(j_id) ?? -1)
let j_name = jsonFile[i]["name"].string ?? "N/A"
name.append(j_name)
let j_lat = jsonFile[i]["coordX"].string ?? "-1.0"
lat.append(Double(j_lat) ?? -1.0)
let j_lon = jsonFile[i]["coordY"].string ?? "-1.0"
lon.append(Double(j_lon) ?? -1.0)
}
for i in 0..<id.count {
mapData.append(coffeeShopsData(shopId : id[i], name : name[i], icon : img[i], latitude : lat[i], longitude : lon[i]))
}
for i in 0..<mapData.count {
let point = MGLPointAnnotation()
point.coordinate = CLLocationCoordinate2D(latitude : mapData[i].latitude ?? 0, longitude : mapData[i].longitude ?? 0)
point.title = mapData[i].name ?? "*Data Error*"
markers.append(point)
}
self.mapView.addAnnotations(markers)
case .failure(let error):
print(error)
}
}
}
}
Error:
libc++abi.dylib: terminating with uncaught exception of type std::domain_error
I'm new in swift, so any advice will be useful

Related

Terminating app due to uncaught exception 'NSRangeException'. libc++abi.dylib: terminating with uncaught exception of type NSException

I get this crash error:
MXNet2CoreML[11383:1168377]
*** Terminating app due to uncaught exception 'NSRangeException', reason:
*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'
*** First throw call stack: (0x18333f164 0x182588528 0x18329a020 0x1007894bc 0x1011ef94c 0x1011b0420 0x1021412cc 0x10214128c
0x102145ea0 0x1832e7344 0x1832e4f20 0x183204c58 0x1850b0f84
0x18c95d5c4 0x1007d8894 0x182d2456c)
libc++abi.dylib: terminating with uncaught exception of type
NSException
Here is the Complete Code
//Owais: - Map setup
func resetRegion(){
let region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, 5000, 5000)
mapKit.setRegion(region, animated: true)
}
var myLatitude = ""
var myLongitude = ""
// Array of annotations
let annotation = MKPointAnnotation()
var places = PredictionLocationList().place
var locationsArray = [String]()
var ie: Int = 0
#IBOutlet var mapKit: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let defaults = UserDefaults.standard
let data = defaults.data(forKey: "selectedimage")
let uiimage2 = UIImage(data: data!)
defaults.synchronize()
let image = uiimage2
// imageView.image = image
predictUsingVision(image: image!)
let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
swipeDown.direction = UISwipeGestureRecognizerDirection.down
self.view.addGestureRecognizer(swipeDown)
// Do any additional setup after loading the view.
}
#objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.right:
print("Swiped right")
case UISwipeGestureRecognizerDirection.down:
print("Swiped down")
self.dismiss(animated: true, completion: nil)
case UISwipeGestureRecognizerDirection.left:
print("Swiped left")
case UISwipeGestureRecognizerDirection.up:
print("Swiped up")
default:
break
}
}
}
func predictUsingVision(image: UIImage) {
guard let visionModel = try? VNCoreMLModel(for: model.model) else {
fatalError("Something went wrong")
}
let request = VNCoreMLRequest(model: visionModel) { request, error in
if let observations = request.results as? [VNClassificationObservation] {
let top3 = observations.prefix(through: 2)
.map { ($0.identifier, Double($0.confidence)) }
self.show(results: top3)
}
}
request.imageCropAndScaleOption = .centerCrop
let handler = VNImageRequestHandler(cgImage: image.cgImage!)
try? handler.perform([request])
}
typealias Prediction = (String, Double)
func show(results: [Prediction]) {
var s: [String] = []
for (i, pred) in results.enumerated() {
let latLongArr = pred.0.components(separatedBy: "\t")
print("lat long \(latLongArr)")
myLatitude = latLongArr[1]
myLongitude = latLongArr[2]
ie = i
s.append(String(format: "%d: %# %# (%.2f%%)", i + 1, myLatitude, myLongitude, pred.1 * 100))
LocationByCoordinates(latitude: myLatitude, longitude: myLongitude)
// let ew1 = (String(format: "%.2f%", pred.1 * 100))
// print(ew1)
// let double1 = Double(ew1)
// self.doubles.append(double1!)
// print("eueue \(self.doubles)")
// let maxDouble = max(max(double1, double2), double3)
print("first latidue \(myLatitude),,,, \(myLongitude)")
places[i].title = String(i+1)
places[i].coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(myLatitude)!, longitude: CLLocationDegrees(myLongitude)!)
}
// predictionLabel.text = s.joined(separator: "\n")
// Map reset
resetRegion()
mapKit.centerCoordinate = places[0].coordinate
// Show annotations for the predictions on the map
mapKit.addAnnotations(places)
// Zoom map to fit all annotations
zoomMapFitAnnotations()
}
func zoomMapFitAnnotations() {
var zoomRect = MKMapRectNull
for annotation in mapKit.annotations {
let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0)
if (MKMapRectIsNull(zoomRect)) {
zoomRect = pointRect
} else {
zoomRect = MKMapRectUnion(zoomRect, pointRect)
}
}
self.mapKit.setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(50, 50, 50, 50), animated: true)
}
func LocationByCoordinates (latitude: String,longitude:String) {
let mapsKey = UserDefaults.standard.string(forKey: "maps_key") ?? ""
Alamofire.request("https://maps.googleapis.com/maps/api/geocode/json?latlng=\(latitude),\(longitude)&key=\(mapsKey)").responseJSON { response in
if let json = response.result.value {
let request = json as? NSDictionary
if let id = request!["results"] {
// print(id)
let ide = id as? NSArray
let formatted_address = ide![0]
let fors = formatted_address as! NSDictionary
//print(fors.value(forKey: "formatted_address"))
let forss = fors.value(forKey: "formatted_address")
self.locationsArray.append(forss as? String ?? "")
if self.ie == 0 {
self.places[0].identifier = (forss as? String)!
} else if self.ie == 1 {
self.places[1].identifier = (forss as? String)!
} else if self.ie == 2 {
self.places[2].identifier = (forss as? String)!
}
}
}
}
}
}
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
The problem is in this line let formatted_address = ide![0]
If an array is empty, you can't get it's first element with [0] because there is no element at all!
All you have to do is check if the array is not empty before unwrapping it:
if ide!.count > 0 {
//Your code
}
To avoid force-unwrapping ide, you may want to use optional binding like so:
if let id = request!["results"], let ide = id as? NSArray {
let formatted_address = ide[0]
let fors = formatted_address as! NSDictionary
//rest of your code
}

SWIFT 4.1 Cannot invoke initializer for type 'Double' with an argument list of type '(String?)'

I'm retrieving mapView annotations posted in Firebase to show them on map, but while converting String values for latitude and longitude to recombine them into CLLocationCoordinates2D I get the error. I don't understand why, because in another function I use the same method but getting the values from arrays but I don't get the error. Also on retrieving the data I would like to also use the key value from firebase as initialiser for my annotations. But I get two more errors Use of unresolved identifier 'firebaseKey' and Use of unresolved identifier 'recombinedCoordinate' for initialisers. Here're the function:
func displayAlerts() {
// FIREBASE: Reference
ref = Database.database().reference()
// FIREBASE:Retrieve posts and listen for changes
databaseHandle = ref?.child("Community").child("Alert Notifications").observe(.childAdded, with: { (snapshot) in
let data = snapshot.value as? [String:String]
if let actualData = data {
let dataLatitude = data!["Latitude"]
let dataLongitude = data!["Longitude"]
self.alertIconToDisplay = data!["Description"]
let doubledLatitude = Double(dataLatitude)
let doubledLongitude = Double(dataLongitude)
var recombinedCoordinate = CLLocationCoordinate2D(latitude: doubledLatitude!, longitude: doubledLongitude!)
print("Firebase post retrieved !")
self.dummyFunctionToFoolFirebaseObservers()
}
let dataKey = snapshot.key as? String
if let firebaseKey = dataKey {
print("Longitude DataKey is \(String(describing: dataKey))")
print("Longitude Actual DataKey is \(String(describing: firebaseKey))")
self.dummyFunctionToFoolFirebaseObservers()
}
print("fir long \((snapshot.value!, snapshot.key))")
userAlertAnnotation = UserAlert(type: self.alertIconToDisplay, coordinate: recombinedCoordinate, firebaseKey: firebaseKey)
self.mapView.addAnnotation(self.userAlertAnnotation)
})
}
Here's the annotation model :
class UserAlert: NSObject , MKAnnotation {
var type: String?
var firebaseKey: String?
var coordinate:CLLocationCoordinate2D
init(type:String, coordinate:CLLocationCoordinate2D, firebaseKey: String) {
self.type = type
self.firebaseKey = firebaseKey
self.coordinate = coordinate
}
}
What am I doing wrong here? I understand that the error on the initialisers are because initialisation occurs in key closures, but how then I incorporate all data into initialiser ?
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: userAlertAnnotation, reuseIdentifier: "") // CHANGE FOR NEW ANNOTATION : FULL DATA
//added if statement for displaying user location blue dot
if annotation is MKUserLocation{
return nil
} else {
annotationView.image = UIImage(named: alertIconToDisplay!) // choose the image to load
let transform = CGAffineTransform(scaleX: 0.27, y: 0.27)
annotationView.transform = transform
return annotationView
}
}
func postAlertNotification() {
// to set next notification id as the position it will have in array ( because first position is 0 ) we use the array.count as value
let latitude = alertNotificationLatitude
let longitude = alertNotificationLongitude
let alertType = alertNotificationType
let post: [String:String] = [//"Date" : date as! String,
//"Time" : time as! String,
"Latitude" : latitude as! String,
"Longitude" : longitude as! String,
"Description" : alertType as! String]
var ref: DatabaseReference!
ref = Database.database().reference()
ref.child("Community").child("Alert Notifications").childByAutoId().setValue(post)
}
The error in the topic says that you can't create a Double from an optional String which is true.
To solve it force unwrap the values for Latitude and Longitude.
But the main issue is a scope issue, all variables used in the initializer must be in the same scope. You can flatten the scope with guard statements:
...
databaseHandle = ref?.child("Community").child("Alert Notifications").observe(.childAdded, with: { (snapshot) in
defer { self.dummyFunctionToFoolFirebaseObservers() }
guard let data = snapshot.value as? [String:String] else { return }
guard let firebaseKey = snapshot.key as? String else { return }
// let date = data!["Date"]
// let time = data!["Time"]
let dataLatitude = data["Latitude"]!
let dataLongitude = data["Longitude"]!
self.alertIconToDisplay = data["Description"]!
let doubledLatitude = Double(dataLatitude)
let doubledLongitude = Double(dataLongitude)
let recombinedCoordinate = CLLocationCoordinate2D(latitude: doubledLatitude!, longitude: doubledLongitude!)
print("Firebase post retrieved !")
// self .keyaLon = dataKey
// self.keyaLonArray.append(firebaseKey)
print("Longitude Actual DataKey is \(String(describing: firebaseKey))")
print("fir long \((snapshot.value!, snapshot.key))")
self.userAlertAnnotation = UserAlert(type: self.alertIconToDisplay, coordinate: recombinedCoordinate, firebaseKey: firebaseKey)
self.mapView.addAnnotation(self.userAlertAnnotation)
})

My weather data is not showing up in my view controller

I can't figure out why my view controller is not showing the data, even though I can see it in the output window.
Output:
Muḩāfaz̧at Al Jīzah
Clear
88.0
my code:
override func viewDidLoad() {
super.viewDidLoad()
loadCurrentWeather = currentWeatherData()
loadCurrentWeather.downloadWeatherData {
//setting uo UI to download data
self.updateTodayUI()
}
}
func updateTodayUI() {
locationLabel.text = loadCurrentWeather.cityName
weatherTypeLabel.text = loadCurrentWeather.weatherType
currentTempLabel.text = "\(loadCurrentWeather.currentTemp)"
weatherTypeImage.image = UIImage(named: loadCurrentWeather.weatherType)
}
My view controller in Xcode:
My view controller on iphone:
currentweatherData the code where I'm downloading the data form.
import UIKit
import Alamofire
class currentWeatherData {
var cityNameone: String!
var dateone: String!
var weatherTypeone: String!
var currentTempone: Double!
var cityName: String {
if cityNameone == nil {
cityNameone = ""
}
return cityNameone
}
var date: String {
if dateone == nil {
dateone = ""
}
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
let currentDate = dateFormatter.string(from: Date())
self.dateone = "Today, \(currentDate)"
return dateone
}
var weatherType: String{
if weatherTypeone == nil{
weatherTypeone = ""
}
return weatherTypeone
}
var currentTemp: Double {
if currentTempone == nil {
currentTempone = 0.0
}
return currentTempone
}
func downloadWeatherData(completed: DownloadComplete){
// to tell alamofire where to download the data
let weatherURL = URL (string: currentWeatherURL)!
Alamofire.request(weatherURL).responseJSON{ response in
let result = response.result
if let dictionary = result.value as? Dictionary<String, AnyObject>{
if let name = dictionary["name"] as? String {
self.cityNameone = name.capitalized
print(self.cityNameone ?? "No city name")
}
if let weather = dictionary["weather"] as? [Dictionary<String, AnyObject>]{
if let main = weather[0]["main"] as? String {
self.weatherTypeone = main.capitalized
print(self.weatherTypeone ?? "No weather type")
}
}
if let main = dictionary["main"] as? Dictionary<String, AnyObject> {
if let currentTemperature = main["temp"] as? Double {
let kelvintoFarenheit = (currentTemperature * (9/5) - 459.67)
let totalKelvinToFarenheit = Double(round(10 * kelvintoFarenheit/10))
self.currentTempone = totalKelvinToFarenheit
print(self.currentTempone ?? .nan)
}
}
}
}
completed()
}
}
Is problem with my code or my view controller? Is it something wrong with my constraints?
I can't seem to figure it out.
You are calling completed too early - before the JSON response arrives. You have to call it inside the closure of the responseJSON call instead:
Alamofire.request(weatherURL).responseJSON { response in
let result = response.result
// ...
completed()
}
I cannot see all of your code to troubleshoot, but you may have a concurrency issue. Try putting the call to updateTodayUI inside of viewDidLoad(_:) inside of an async block like this:
DispatchQueue.main.async {
updateTodayUI()
}
You can find more information on dispatch queues and concurrency in the documentation.

How to iterate through Swift array and use data in iOS Chart?

I have a bar chart, which I am trying to populate through data pulled in from an array.
I am trying to iterate through this array in order to populate my chart.
Please note: in this example below there are 3 winningStreakDM variables hardcoded for testing purposes, but in 'real life' the number could be different each API call as it depends on how many 'users' are in that league.
This is why I need to iterate through the array and structure the data to suit.
let winningStreakDM1 : [String : Any] = [
"id" : 2,
"user_name" : "Dicky",
"winning_streak" : 5
]
let winningStreakDM2 : [String : Any] = [
"id" : 6,
"user_name" : "G",
"winning_streak" : 2
]
let winningStreakDM3 : [String : Any] = [
"id" : 5,
"user_name" : "Sultan",
"winning_streak" : 0
]
My issue is that I don't know how to iterate through the initial array to structure my data for it to work with the above code.
This is my full script:
import UIKit
import Charts
class CommunityLeagueStatsVC: UIViewController {
// GRAPHS *********
#IBOutlet weak var chartView: BarChartView!
var values = [BarChartDataEntry]()
// ****************
//********CHART VARIABLES**************//
//WINS LOSSES DRAWS
var winStreak: Double = 0.0
#IBOutlet weak var leagueStatsScrollView: UIScrollView!
var noDefeats: Bool?
var noWins: Bool?
var biggestWin: String?
var biggestWinTeams: String?
var passedCommunityName: String?
#IBOutlet weak var communityName: UILabel!
var playerId2: String?
var communityId2: String?
var eMail2: String?
override func viewDidLoad() {
super.viewDidLoad()
let winningStreak = ["Wins"]
let gamesWon = [winStreak]
setWinStreakChart(dataPoints: winningStreak, values: gamesWon)
let defaults = UserDefaults.standard
let Email = defaults.string(forKey: "userEmail")
let playerId = defaults.string(forKey: "playerId")
let commsId = defaults.string(forKey: "communityId")
self.playerId2 = playerId
self.communityId2 = commsId
self.eMail2 = Email
}
func setWinStreakChart(dataPoints: [String], values: [BarChartDataEntry]){
xAxis.valueFormatter = WinningStreakFormatter(chartView: self.chartView)
let barChartDataSet = BarChartDataSet(values: values, label: "Winning Streak")
barChartDataSet.colors = ChartColorTemplates.material()
let barChartData = BarChartData(dataSet: barChartDataSet)
barChartData.setValueFont(UIFont.systemFont(ofSize: 12.0))
self.chartView.data = barChartData
}
override func viewDidAppear(_ animated: Bool) {
let myUrl = URL(string: "http://www.xxx.uk/xxx/getLeagueStats.php")
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"
let postString = "player_id=\(self.playerId2!)&community_id=\(communityId2!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json!)
if let dict = json?["leagueStats"] as? [String:AnyObject] {
//WINNING STREAK
var values = [BarChartDataEntry]()
if let dataWinStreak = dict["winningStreak"] as? [[String : Any]] {
print ("test one")
for (index,item) in dataWinStreak.enumerated() {
if let yValue = item["winning_streak"] as? Int, let userName = item["user_name"] as? String {
print ("test two")
let barChartDataEntry = BarChartDataEntry(x: Double(index), y: Double(yValue), data: userName as AnyObject?)
values.append(barChartDataEntry)
}
}
self.setWinStreakChart(dataPoints: ["wins"], values: values)
}
catch{
print(error)
}
}
}
task.resume()
}
}
UPDATE:
These are the errors that I am currently receiving:
With a bit of playing around and commenting out the line containing the first error I have got to this stage which correctly shows a graph with values, but no xAxis containing the userNames of each player.
You can create array of BarChartDataEntry this way.
var values = [BarChartDataEntry]()
if let dataWinStreak = dict["winningStreak"] as? [[String : Any]] {
for (index,item) in dataWinStreak.enumerated() {
if let yValue = item["winning_streak"] as? Int, let userName = item["user_name"] as? String {
let barChartDataEntry = BarChartDataEntry(x: index, y: yValue, data: userName)
values.append(barChartDataEntry)
}
}
}
//Now use values array
Edit: You just need to change setWinStreakChart function because now you are working with dynamic data not static one.
func setWinStreakChart(dataPoints: [String], values: [BarChartDataEntry]){
let xAxis : XAxis = self.chartView.xAxis;
xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10.0)!
xAxis.labelTextColor = UIColor.black
xAxis.drawAxisLineEnabled = false
xAxis.drawGridLinesEnabled = true
xAxis.granularity = 1;
xAxis.labelPosition = .bottom
xAxis.valueFormatter = WinningStreakFormatter(chartView: self.chartView)
let barChartDataSet = BarChartDataSet(values: values, label: "Winning Streak")
barChartDataSet.colors = ChartColorTemplates.material()
let barChartData = BarChartData(dataSet: barChartDataSet)
barChartData.setValueFont(UIFont.systemFont(ofSize: 12.0))
self.chartView.data = barChartData
}
And now call this function after the for loop where we are creating array of BarChartDataEntry.
self.setWinStreakChart(dataPoints: ["wins"], values: values)

Convert optional string to double in Swift 3

I have a option string and want to convert that to double.
this worked in Swift 2 , but since converted to Swift 3, I am getting value of 0.
var dLati = 0.0
dLati = (latitude as NSString).doubleValue
I have check and latitude has a optional string value of something like -80.234543218675654 , but dLati value is 0
*************** ok, new update for clarity *****************
I have a viewcontroller which i have a button in it, and when the button is touched, it will call another viewcontroller and pass a few values to it
here is the code for the first viewcontroller
var currentLatitude: String? = ""
var currentLongitude: String? = ""
var deviceName = ""
var address = ""
// somewhere in the code, currentLatitude and currentLongitude are get set
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "map" {
let destViewController : MapViewController = segue.destination as! MapViewController
print(currentLongitude!) // Print display: Optional(-80.192279355363768)
print(currentLatitude!) // Print display: Optional(25.55692663937162)
destViewController.longitude = currentLongitude!
destViewController.latitude = currentLatitude!
destViewController.deviceName = deviceName
destViewController.address = address
}
}
Here is the code for the second view controller called MapViewController
var longitude: String? = " "
var latitude: String? = ""
.
.
override func viewDidLoad() {
if let lat = latitude {
print(lat) // Print display: optiona(25.55692663937162)
dLati = (lat as NSString).doubleValue
print(dLati) // Print display: 0.0
}
.
.
}
Thanks
Borna
A safe way to achieve this without needing to use Foundation types is using Double's initializer:
if let lat = latitude, let doubleLat = Double(lat) {
print(doubleLat) // doubleLat is of type Double now
}
Unwrap the latitude value safely and then use
var dLati = 0.0
if let lat = latitude {
dLati = (lat as NSString).doubleValue
}
let dLati = Double(latitude ?? "") ?? 0.0
This code works fine.
var dLati = 0.0
let latitude: String? = "-80.234543218675654"
if let strLat = latitude {
dLati = Double(strLat)!
}
You can do this simply in one line.
var latitude: Double = Double("-80.234543218675654") ?? 0.0
This creates a variable named latitude that is of type Double that is either instantiated with a successful Double from String or is given a fallback value of 0.0
When you get a string with double value something like this
"Optional(12.34567)"
You can use a Regex which takes out the double value from the string.
This is the example code for a Regex if the string is "Optional(12.34567)":
let doubleLatitude = location.latitude?.replacingOccurrences(of: "[^\\.\\d+]", with: "", options: [.regularExpression])
Actually the word optional was part of the string. Not sure how it got added in the string? But the way I fixed it was like this. latitude was this string "Optional(26.33691567239162)" then I did this code
let start = latitude.index(latitude.startIndex, offsetBy: 9)
let end = latitude.index(latitude.endIndex, offsetBy: -1)
let range = start..<end
latitude = latitude.substring(with: range)
and got this as the final value
26.33691567239162
Don´t convert it to an NSString, you can force it to a Double but have a fallback if it fails. Something like this:
let aLat: String? = "11.123456"
let bLat: String? = "11"
let cLat: String? = nil
let a = Double(aLat!) ?? 0.0 // 11.123456
let b = Double(bLat!) ?? 0.0 // 11
let c = Double(cLat!) ?? 0.0 // 0
So in your case:
dLati = Double(latitude!) ?? 0.0
Update:
To handle nil values do the following (note that let cLat is nil:
// Will succeed
if let a = aLat, let aD = Double(aLat!) {
print(aD)
}
else {
print("failed")
}
// Will succeed
if let b = bLat, let bD = Double(bLat!) {
print(bD)
}
else {
print("failed")
}
// Will fail
if let c = cLat, let cD = Double(cLat!) {
print(cD)
}
else {
print("failed")
}
In swift 3.1, we can combine extensions and Concrete Constrained Extensions
extension Optional where Wrapped == String
{
var asDouble: Double
{
return NSString(string: self ?? "").doubleValue
}
}
Or
extension Optional where Wrapped == String
{
var asDouble: Double
{
return Double(str ?? "0.00") ?? 0.0
}
}
Swift 4
let YourStringValue1st = "33.733322342342" //The value is now in string
let YourStringValue2nd = "73.449384384334" //The value is now in string
//MARK:- For Testing two Parameters
if let templatitude = (YourStringValue1st as? String), let templongitude = (YourStringValue2nd as? String)
{
movetosaidlocation(latitude: Double(templat)!, longitude: Double(templong)!, vformap: cell.vformap)
}
let YourStringValue = "33.733322342342" //The value is now in string
//MARK:- For Testing One Value
if let tempLat = (YourStringValue as? String)
{
let doublevlue = Double(tempLat)
//The Value is now in double (doublevlue)
}

Resources