NSRangeException error after login successfully into the app

Everything is functional and the app is operational, no errors detected.

The error appears when I try to login into the app the login is successfully but an error pops



2018-10-22 14:08:22.109588-0500 123Taxi[3213:960305] A location manager (0x102613cf0) was created on a dispatch queue executing on a thread other than the main thread.  It is the developer's responsibility to ensure that there is a run loop running on the thread on which the location manager object is allocated.  In particular, creating location managers in arbitrary dispatch queues (not attached to the main queue) is not supported and will result in callbacks not being received.
2018-10-22 14:08:22.120911-0500 123Taxi[3213:960305] [Animation] +[UIView setAnimationsEnabled:] being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior. trace=(
  0   UIKitCore                           0x00000001ec06ded8  + 136
  1   libdispatch.dylib                   0x0000000101fecde4 _dispatch_client_callout + 16
  2   libdispatch.dylib                   0x0000000101feee44 _dispatch_once_callout + 84
  3   UIKitCore                           0x00000001ec06de4c  + 100
  4   UIKitCore                           0x00000001ebd6a1a0  + 276
  5   UIKitCore                           0x00000001ebd6a05c  + 92
  6   UIKitCore                           0x00000001eb617cdc  + 108
  7   123Taxi                             0x0000000100f6cc3c $S7_23Taxi14ViewControllerC13iniciarSesionyySo8UIButtonCFy10Foundation4DataVSg_So13NSURLResponseCSgs5Error_pSgtcfU_ + 2252
  8   123Taxi                             0x0000000100f6d280 $S10Foundation4DataVSgSo13NSURLResponseCSgs5Error_pSgIegggg_So6NSDataCSgAGSo7NSErrorCSgIeyByyy_TR + 316
  9   CFNetwork                           0x00000001bf3807bc  + 32
  10  CFNetwork                           0x00000001bf394f5c  + 176
  11  Foundation                          0x00000001bf833b6c  + 16
  12  Foundation                          0x00000001bf73bcc8  + 72
  13  Foundation                          0x00000001bf73b19c  + 740
  14  Foundation                          0x00000001bf835a40  + 272
  15  libdispatch.dylib                   0x0000000101feb840 _dispatch_call_block_and_release + 24
  16  libdispatch.dylib                   0x0000000101fecde4 _dispatch_client_callout + 16
  17  libdispatch.dylib                   0x0000000101ff01e0 _dispatch_continuation_pop + 528
  18  libdispatch.dylib                   0x0000000101fef620 _dispatch_async_redirect_invoke + 632
  19  libdispatch.dylib                   0x0000000101ffe1f8 _dispatch_root_queue_drain + 376
  20  libdispatch.dylib                   0x0000000101ffebe4 _dispatch_worker_thread2 + 156
  21  libsystem_pthread.dylib             0x00000001be9c2190 _pthread_wqthread + 472
  22  libsystem_pthread.dylib             0x00000001be9c4d00 start_wqthread + 4
)
2018-10-22 14:08:22.129449-0500 123Taxi[3213:960305] *** Terminating app due to uncaught exception 'NSRangeException', reason: ' initWithCoder:: MKMapView must be initialized on the main thread.'
*** First throw call stack:
(0x1beda7ef8 0x1bdf75a40 0x1becacac4 0x1cfb122ac 0x1c93c3e88 0x1c9362b3c 0x1eb8853b4 0x1c93c3e88 0x1c93c40cc 0x1c9362b3c 0x1eb882cb4 0x1eb6143d0 0x1eb614d7c 0x1eb615044 0x1eb6157b0 0x1eb5484c8 0x1eb53c79c 0x1eb626c98 0x1eb629bac 0x1eb62a210 0x1eb629b04 0x1eb629e40 0x1ebd652e4 0x1ebd6a1b0 0x1ebd6a05c 0x1eb617cdc 0x100f6cc3c 0x100f6d280 0x1bf3807bc 0x1bf394f5c 0x1bf833b6c 0x1bf73bcc8 0x1bf73b19c 0x1bf835a40 0x101feb840 0x101fecde4 0x101ff01e0 0x101fef620 0x101ffe1f8 0x101ffebe4 0x1be9c2190 0x1be9c4d00)
libc++abi.dylib: terminating with uncaught exception of type NSException

So this is the Login code

import UIKit
import Alamofire

class ViewController: UIViewController {

    @IBOutlet var Email: UITextField!
    @IBOutlet var Contrasena: UITextField!
    var iconClick : Bool!
    
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        iconClick = true
       
       if UserDefaults.standard.bool(forKey: "UserisLog") == true
       {
       
        
        }
        // Do any additional setup after loading the view, typically from a nib.
    }

    
    @IBAction func verlacontra(_ sender: UIButton) {
        let userPazzword = Contrasena.text!;
        
        if(iconClick == true) {
            Contrasena.isSecureTextEntry = false
            iconClick = false
        } else {
            Contrasena.isSecureTextEntry = true
            iconClick = true
        }
        
    }
    
    
    //func para mostrar alerta si no se introduce nada
    
    @IBAction func iniciarSesion(_ sender: UIButton) {
        //### User guard-let when you check sort of required condition
        guard
            let emailText = Email.text, !emailText.isEmpty,
            let contrasenaText = Contrasena.text, !contrasenaText.isEmpty else
        {
            displayAlert(title: "Información Faltante", message: "Debes porporcionar un correo y contraseña")
            return
        }
        
        let myURL = URL(string: ":C:CCCc") //### Use `URL` rather than `NSURL`
        var request = URLRequest(url: myURL!) //### Use `URLRequest` as `var` rather than `NSMutableURLRequest`
        request.httpMethod = "POST"
        let posString = "Email=\(emailText)&Password=\(contrasenaText)" //### You need non-Optional here
        request.httpBody = posString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) {
            data, response, error in
            
            if let error = error {
                print("error=\(error)")
                return
            }
            
            guard let data = data else {
                print("Something wrong")
                return
            }
            //var err : NSError? //### You need do-try-catch instead of declaring a variable of `NSError?`
            
            struct Blog: Decodable {
                let Response: String
                let articles: [Article]
                
                enum CodingKeys : String, CodingKey {
                    case Response
                    
                    case articles = "Perfil"
                }
            }
            
            struct Article: Decodable {
                let id: String
                let Nombre: String
                let Email: String
                let Telefono: String
                let Email_Contacto: String
                let Telefono_Contacto: String
                let Nivel: String
            }
           
            
       
            guard let blog = try? JSONDecoder().decode(Blog.self, from: data) else {
                print("Error: Couldn't decode data into Blog")
                return
            }
            
            
           if blog.Response == "true"
           {
            for article in blog.articles {
               //aqui guardar los articulos que son id,nombre,email,etc
                let emailcapturado = article.Email
                
                if emailcapturado == emailText{
                 UserDefaults.standard.set(true, forKey: "UserisLog")
                    UserDefaults.standard.synchronize()
                    self.performSegue(withIdentifier: "logeadoSegue", sender: nil)
                }
                
            }
        }
           else if  blog.Response == "false"{
            self.displayAlert(title: "Usuario", message: "Contraseña incorrecta")
            }
           else if  blog.Response == "nothing"{
            self.displayAlert(title: "Información", message: "Usuario no existe")
            }
    }
        task.resume()
    }
    
    func displayAlert (title:String, message:String){
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
        self.present(alertController, animated: true, completion: nil)
        
    }
    
    
    @IBAction func forgotPass(_ sender: UIButton) {
        self.performSegue(withIdentifier: "gotoRecuperacion", sender: nil)
    }
    
    
    @IBAction func crearCuenta(_ sender: UIButton) {
        self.performSegue(withIdentifier: "gotoquieneres", sender: nil)
    }
    
    
    
    
    //funcion para el teclado que regrese
    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        self.view.endEditing(true)
    }
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

    

}


and the map code


import UIKit
import MapKit
import CoreLocation

class UnaVezLogeadoViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
    @IBOutlet var map: MKMapView!

    @IBOutlet var buttonOulet: UIButton!
    
    @IBOutlet var coordLat: UILabel!
    @IBOutlet var coordLong: UILabel!
    
    
    
    
    let locationManager = CLLocationManager()
    
    override func viewDidLoad() {
        self.locationManager.requestAlwaysAuthorization()
        
        // For use in foreground
        self.locationManager.requestWhenInUseAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        //funcion para hacer request a la ubicacion cuando usa el botón
        // la funcion empieza a localizarte
        locationManager.startUpdatingLocation()
        
        if CLLocationManager.locationServicesEnabled() {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.startUpdatingLocation()
        }
    
        
        map.delegate = self
        map.mapType = .standard
        map.isZoomEnabled = true
        map.isScrollEnabled = true
        
        map.showsUserLocation = true
       
        
        if let coor = map.userLocation.location?.coordinate{
            map.setCenter(coor, animated: true)
           
        }
        
       
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let locValue:CLLocationCoordinate2D = manager.location!.coordinate
        
        map.mapType = MKMapType.standard
        
        let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
        let region = MKCoordinateRegion(center: locValue, span: span)
        map.setRegion(region, animated: true)
        
        /*
        let annotation = MKPointAnnotation()
        annotation.coordinate = locValue
        annotation.title = "Yo"
        annotation.subtitle = "current location"
        map.addAnnotation(annotation)
 */

        
        self.coordLat.text = "latitude: " + String(manager.location!.coordinate.latitude)
        self.coordLong.text = "longitude: " + String(manager.location!.coordinate.longitude)
        
    }
    
    @IBAction func iniciar(_ sender: UIButton) {
        
        
        let request = NSMutableURLRequest(url: NSURL(string: "hehe")! as URL)
        request.httpMethod = "POST"
        let postString = "Latitud=\(coordLat.text!)&Longitud=\(coordLong.text!)"
        request.httpBody = postString.data(using: String.Encoding.utf8)
        
        let task = URLSession.shared.dataTask(with: request as URLRequest) {
            data, response, error in
            
            if error != nil {
                print("error=\(String(describing: error))")
                
                
                return
            }
            
            print("response = \(String(describing: response))")
            
            let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            print("responseString = \(String(describing: responseString))")
            
            
        }
        task.resume()
        
        }
    
    
    
    
    
    
        
    }

Accepted Reply

Seems you have gotten a step ahead since your last thread.

You should better know that answerers would be very happy to hear that you solved your issue.


Read carefully some lines of the log you have shown:

2018-10-22 14:08:22.109588-0500 123Taxi[3213:960305] A location manager (0x102613cf0) was created on a dispatch queue executing on a thread other than the main thread. It is the developer's responsibility to ensure that there is a run loop running on the thread on which the location manager object is allocated. In particular, creating location managers in arbitrary dispatch queues (not attached to the main queue) is not supported and will result in callbacks not being received.

2018-10-22 14:08:22.120911-0500 123Taxi[3213:960305] [Animation] +[UIView setAnimationsEnabled:] being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior. trace=(

...

2018-10-22 14:08:22.129449-0500 123Taxi[3213:960305] *** Terminating app due to uncaught exception 'NSRangeException', reason: ' initWithCoder:: MKMapView must be initialized on the main thread.'


Seems your code has some thread issues.

Generally, you need to call any UI-related methods in the main thread, so if you want to call them in the completion handler of `dataTask`, you need to enclose them in `Dispatch.main.async {...}`.


An example:

    @IBAction func iniciarSesion(_ sender: UIButton) {
        guard
            let emailText = email.text, !emailText.isEmpty,
            let contrasenaText = contrasena.text, !contrasenaText.isEmpty else
        {
            displayAlert(title: "Información Faltante", message: "Debes porporcionar un correo y contraseña")
            return
        }
        
        let myURL = URL(string: ":C:CCCc")
        var request = URLRequest(url: myURL!)
        request.httpMethod = "POST"
        let posString = "Email=\(emailText)&Password=\(contrasenaText)"
        request.httpBody = posString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) {
            data, response, error in
            
            if let error = error {
                print("error=\(error)")
                return
            }
            
            guard let data = data else {
                print("Something wrong")
                return
            }
            
            struct Blog: Decodable {
                let response: String
                let articles: [Article]
                
                enum CodingKeys : String, CodingKey {
                    case response = "Response"
                    case articles = "Perfil"
                }
            }
            
            struct Article: Decodable {
                let id: String
                let nombre: String
                let email: String
                let telefono: String
                let emailContacto: String
                let telefonoContacto: String
                let nivel: String
                
                enum CodingKeys : String, CodingKey {
                    case id = "id"
                    case nombre = "Nombre"
                    case email = "Email"
                    case telefono = "Telefono"
                    case emailContacto = "Email_Contacto"
                    case telefonoContacto = "Telefono_Contacto"
                    case nivel = "Nivel"
                }
            }
            
            do {
                //### You should better not dispose error info using `try?`
                let blog = try JSONDecoder().decode(Blog.self, from: data)

                //### Do any UI manipulations in the main thread
                DispatchQueue.main.async {
                    if blog.response == "true" {
                        for article in blog.articles {
                            //aqui guardar los articulos que son id,nombre,email,etc
                            let emailcapturado = article.email
                            
                            if emailcapturado == emailText{
                                UserDefaults.standard.set(true, forKey: "UserisLog")
                                UserDefaults.standard.synchronize()
                                self.performSegue(withIdentifier: "logeadoSegue", sender: nil)
                                break //###
                            }
                        }
                    } else if  blog.response == "false" {
                        self.displayAlert(title: "Usuario", message: "Contraseña incorrecta")
                    } else if  blog.response == "nothing" {
                        self.displayAlert(title: "Información", message: "Usuario no existe")
                    }
                }
            } catch {
                print("Error: Couldn't decode data into Blog:", error)
                return
            }
        }
        task.resume()
    }

I modified some parts unrelated to the issue, as using capitalized identifier for non-type in Swift is sort of creeping for me. You may need to fix them to fit my code into your ViewController.

Replies

Seems you have gotten a step ahead since your last thread.

You should better know that answerers would be very happy to hear that you solved your issue.


Read carefully some lines of the log you have shown:

2018-10-22 14:08:22.109588-0500 123Taxi[3213:960305] A location manager (0x102613cf0) was created on a dispatch queue executing on a thread other than the main thread. It is the developer's responsibility to ensure that there is a run loop running on the thread on which the location manager object is allocated. In particular, creating location managers in arbitrary dispatch queues (not attached to the main queue) is not supported and will result in callbacks not being received.

2018-10-22 14:08:22.120911-0500 123Taxi[3213:960305] [Animation] +[UIView setAnimationsEnabled:] being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior. trace=(

...

2018-10-22 14:08:22.129449-0500 123Taxi[3213:960305] *** Terminating app due to uncaught exception 'NSRangeException', reason: ' initWithCoder:: MKMapView must be initialized on the main thread.'


Seems your code has some thread issues.

Generally, you need to call any UI-related methods in the main thread, so if you want to call them in the completion handler of `dataTask`, you need to enclose them in `Dispatch.main.async {...}`.


An example:

    @IBAction func iniciarSesion(_ sender: UIButton) {
        guard
            let emailText = email.text, !emailText.isEmpty,
            let contrasenaText = contrasena.text, !contrasenaText.isEmpty else
        {
            displayAlert(title: "Información Faltante", message: "Debes porporcionar un correo y contraseña")
            return
        }
        
        let myURL = URL(string: ":C:CCCc")
        var request = URLRequest(url: myURL!)
        request.httpMethod = "POST"
        let posString = "Email=\(emailText)&Password=\(contrasenaText)"
        request.httpBody = posString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) {
            data, response, error in
            
            if let error = error {
                print("error=\(error)")
                return
            }
            
            guard let data = data else {
                print("Something wrong")
                return
            }
            
            struct Blog: Decodable {
                let response: String
                let articles: [Article]
                
                enum CodingKeys : String, CodingKey {
                    case response = "Response"
                    case articles = "Perfil"
                }
            }
            
            struct Article: Decodable {
                let id: String
                let nombre: String
                let email: String
                let telefono: String
                let emailContacto: String
                let telefonoContacto: String
                let nivel: String
                
                enum CodingKeys : String, CodingKey {
                    case id = "id"
                    case nombre = "Nombre"
                    case email = "Email"
                    case telefono = "Telefono"
                    case emailContacto = "Email_Contacto"
                    case telefonoContacto = "Telefono_Contacto"
                    case nivel = "Nivel"
                }
            }
            
            do {
                //### You should better not dispose error info using `try?`
                let blog = try JSONDecoder().decode(Blog.self, from: data)

                //### Do any UI manipulations in the main thread
                DispatchQueue.main.async {
                    if blog.response == "true" {
                        for article in blog.articles {
                            //aqui guardar los articulos que son id,nombre,email,etc
                            let emailcapturado = article.email
                            
                            if emailcapturado == emailText{
                                UserDefaults.standard.set(true, forKey: "UserisLog")
                                UserDefaults.standard.synchronize()
                                self.performSegue(withIdentifier: "logeadoSegue", sender: nil)
                                break //###
                            }
                        }
                    } else if  blog.response == "false" {
                        self.displayAlert(title: "Usuario", message: "Contraseña incorrecta")
                    } else if  blog.response == "nothing" {
                        self.displayAlert(title: "Información", message: "Usuario no existe")
                    }
                }
            } catch {
                print("Error: Couldn't decode data into Blog:", error)
                return
            }
        }
        task.resume()
    }

I modified some parts unrelated to the issue, as using capitalized identifier for non-type in Swift is sort of creeping for me. You may need to fix them to fit my code into your ViewController.

yeah, I usually replay and put the answer on the thread but, like you said this is an apple forum, not a PHP forum, and all the answers lead to the PHP.

Also, thx for responding and as told you before i will improve my coding


i still don't understand this line


DispatchQueue.main.async


and i even read your code and added myself by typing not copy/pasting problem solve and many thanks

put the answer on the thread but, like you said this is an apple forum, not a PHP forum, and all the answers lead to the PHP

Just a single line I could have fixed my PHP code or something like that would be enough to make me happy.


This is a well-known idiom to execute some code in the main thread.

DispatchQueue.main.async {
    //...
}

When you work with some asynchronous methods like `URLSession.shared.dataTask`, you may need to use it.


You can learn Dispatch if you prefer to go deeply inside it now, but many other features of Dispatch libraries are not so often used.

You may need some of them in the future, but you can delay to learn it until then.

thanks