skip to Main Content

I am trying to login with macbook using code but I keep on getting this error:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

// API to log an user in
func login(userType: String, completionHandler: @escaping (NSError?) -> Void) {

    let path = "api/social/convert-token/"
    let url = baseURL!.appendingPathComponent(path)
    let params: [String: Any] = [
        "grant_type": "convert_token",
        "client_id": CLIENT_ID,
        "client_secret": CLIENT_SECRET,
        "backend": "facebook",
        "token": FBSDKAccessToken.current().tokenString,
        "user_type": userType
    ]

    Alamofire.request(url!, method: .post, parameters: params, encoding: URLEncoding(), headers: nil).responseJSON { (response) in

        switch response.result {
        case .success(let value):

            let jsonData = JSON(value)

            self.accessToken = jsonData["access_token"].string!
            self.refreshToken = jsonData["refresh_token"].string!
            self.expired = Date().addingTimeInterval(TimeInterval(jsonData["expire_in"].int!))

            completionHandler(nil)
            break

        case .failure(let error):
            completionHandler(error as NSError?)
            break
        }
    }

}

The error is referring to this line:

self.accessToken = jsonData["access_token"].string!

and this is LoginViewController code:

import UIKit
import FBSDKLoginKit

class LoginViewController: UIViewController {
    @IBOutlet weak var bLogin: UIButton!
    @IBOutlet weak var bLogout: UIButton!

    var fbLoginSuccess = false
    var userType: String = USERTYPE_CUSTOMER

    override func viewDidLoad() {
        super.viewDidLoad()

        if (FBSDKAccessToken.current() != nil) {
            bLogout.isHidden = false
            FBManager.getFBUserData(completionHandler: {

                self.bLogin.setTitle("Continue as (User.currentUser.email!)", for: .normal)
                // self.bLogin.sizeToFit()
            })
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        if (FBSDKAccessToken.current() != nil && fbLoginSuccess == true) {
            performSegue(withIdentifier: "CustomerView", sender: self)
        }
    }

    @IBAction func facebookLogout(_ sender: AnyObject) {
        APIManager.shared.logout { (error) in
            if error == nil {
                FBManager.shared.logOut()
                User.currentUser.resetInfo()

                self.bLogout.isHidden = true
                self.bLogin.setTitle("Login with Facebook", for: .normal)
            }
        }
    }

    @IBAction func facebookLogin(_ sender: AnyObject) {
        if (FBSDKAccessToken.current() != nil) {
            APIManager.shared.login(userType: userType, completionHandler:  { (error) in
                if error == nil {
                    self.fbLoginSuccess = true
                    self.viewDidAppear(true)
                }
            })
        } else {
            FBManager.shared.logIn(
                withReadPermissions: ["public_profile", "email"],
                from: self,
                handler: { (result, error) in
                    if (error == nil) {
                        FBManager.getFBUserData(completionHandler: {
                            APIManager.shared.login(userType: self.userType, completionHandler:  { (error) in
                                if error == nil {
                                    self.fbLoginSuccess = true
                                    self.viewDidAppear(true)
                                }
                            })
                        })
                    }
            })
        }
    }
}

Swift 3
Xcode 9
iOS 10.2

I read several texts to find out the causes of this type of error but not succeed.

2

Answers


  1. First of all, it is a bad practice to use force unwrap (!) everywhere. Try to avoid it, until you really need it and/or know what are you doing. Here you use SwiftyJSON. It helps you to extract data from JSON in a convenient way. But you shouldn’t rely, that you will always get proper JSON from the backend. There are many reasons why it can return wrong JSON and there would not be needed value. There are two options:

    1. You can use .stringValue instead of .string – it will return an empty string instead of nil
    2. You can do in this way: if let token = jsonData["access_token"].string {...} or even use guard statement

    Here is a good article to understand force unwrapping: https://blog.timac.org/2017/0628-swift-banning-force-unwrapping-optionals/

    Login or Signup to reply.
  2. This error happens when you have a ! (force unwrap symbol), meaning that you’re certain the data will be there; but in fact, the data isn’t there – it’s nil.

    Try using a guard statement. For example:

    guard let self.accessToken = jsonData["access_token"].string else {
        // log error message, if desired; then exit the function
        return
    }
    

    Alternatively, you could use an if let statement:

    if let self.accessToken = jsonData["access_token"].string {
        // do stuff if 'jsonData["access_token"].string' is valid
    }
    else {
        // do other stuff if 'jsonData["access_token"].string' is nil
    }
    

    Now, why the data is not there (nil) – that’s another question. Perhaps check your JSON function to ensure it’s properly processing the JSON response. Also, check to make sure you’re getting a valid response:

    guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode == 200 else {
        // handle a bad response code
        return
    }
    
    // handle the good response code stuff after the guard statement
    

    Learn about using if let to handle possible nil values in the Swift Programming Language (Swift 4.2) Guide under Optional Binding in the Basics section.

    Learn about guard statements under Early Exit in the Control Flow section of the Guide, and also in the Statements section of the Reference.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search