2

I have this method that was working in Swift 2.2 but ever since I converted my code to Swift 3 it no longer works, what this method does is take a username and password login into a URL with Windows Authentication, if the creds are correct it returns true, if they are not correct, it will return false.

Here is the method:

func loginUser(_ username: String, password: String, completion: @escaping (_ result: Bool) -> Void)
    {
        //Setup the NSURLSessionConfiguration

        let configuration = URLSessionConfiguration.default

        //Setup the NSURLSession

        let session = Foundation.URLSession(configuration: configuration, delegate: self, delegateQueue: nil)

        //Add the username and password to NSURLCredential

        credential = URLCredential(user:username, password:password, persistence: .forSession)

        //Create request URL as String

        let requestString = NSString(format:"%@", webservice) as String

        //Convert URL string to NSURL

        let url: URL! = URL(string: requestString)

        //Prepare the task to get data.

        let task = session.dataTask(with: url, completionHandler: {
            data, response, error in

            DispatchQueue.main.async(execute: {

                if(error == nil)
                {

                    //If there is no error calling the API, return true

                    completion(true)
                }
                else
                {

                    //If there is an error calling the API, return false

                    completion(false)
                }

            })

        })

        //Run the task to get data.

        task.resume()

    }

and I get this error:

fatal error: unexpectedly found nil while unwrapping an Optional value

this occurs right here:

let task = session.dataTask(with: url, completionHandler: {
            data, response, error in

            DispatchQueue.main.async(execute: {

                if(error == nil)
                {

                    //If there is no error calling the API, return true

                    completion(true)
                }
                else
                {

                    //If there is an error calling the API, return false

                    completion(false)
                }

            })

        })

What am I doing wrong?

This appears in my Debug navigator before the fatal error:

function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer <A> ((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A

I believe my problem is here:

/**
     Requests credentials from the delegate in response to a session-level authentication request from the remote server.
     */

    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

        if challenge.previousFailureCount > 0
        {
            completionHandler(Foundation.URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
        }
        else
        {
            completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:challenge.protectionSpace.serverTrust!))
        }

    }

    /**
     Requests credentials from the delegate in response to an authentication request from the remote server.
     */

    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

        completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential,credential)

    }

it doesn't like these methods.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
user979331
  • 11,039
  • 73
  • 223
  • 418

2 Answers2

-1

Change the URL declaration from

let url: URL! = URL(string: requestString)

to:

let url: URL = URL(string: requestString)!

That alone might fix it; or it will show that your requestString is bad.

Graham Perks
  • 23,007
  • 8
  • 61
  • 83
-1

This answer is for those having this problem but in different way.
Here is what i'm facing and fix: I have a searching field to look some results in tableview.
And it crash by digit or erase words and digiting fast as possible. I put a Exception Break Point, but not showing where it crash. So a got back in treads and it begin on this:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "iTableViewCell", for: indexPath) as! MyClassTableViewCell
    cell.setCellFood(with: self.elementsArray[indexPath.row]) // <-- HERE
    return cell
}

But, to get there when digiting, it begin here:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    self.elementsArray.removeAll() // <-- Last thing debbuging i found stop here

    DispatchQueue.main.asyncAfter(deadline: .now()) {
        if textField == self.txtSearch && (textField.text?.characters.count)! > 3 {
            let predicate = NSPredicate(format: "status = 'A' AND name CONTAINS [cd] %@", textField.text!)
            let filtered = MyObjectRealm().get(withFilter: "", predicate: nil, nsPredicate: predicate)
            filtered.forEach({ (food) in
                self.elementsArray.append(food)
                self.reloadAllDataCustom()
            })
        }else{
            self.elementsArray = MyObjectRealm().get(withFilter: "status = 'A'")
            self.reloadAllDataCustom()
        }
    }

    return true
}

So, when it removes all elements, it crash!
The problem is the DispatchQueue.main.asyncAfter(deadline: .now()).
It had a dalay of .now() + 0.2 and then, it is not had time to reload elements again, causing the crash!
Now it is realtime erasing and populating and never crash again, because it never return nil when populate cells.

Hope to help someone to debbuging and find the error too!

Daniel Arantes Loverde
  • 2,317
  • 2
  • 28
  • 41