completion handler's error in swift 3 and Xcode 8
Solution 1
Though I didn't know the error before that what Xcode want to inform me about the error, but I have removed type specification with object and it worked.
As
manager.post(methodname, parameters: param, progress: nil, success:{ (dataTask, responseObj) in
if let dict : NSDictionary = responseObj as? NSDictionary {
print("Response of \(methodname) : \(dict)")
if dict.object(forKey: "response") as? String == "success" {
CompletionHandler(true, dict)
} else {
CompletionHandler(false, dict)
}
}
})
Here with respect to question error is given at dataTask
and responseObj
which are with type specified. After removing type it worked fine.
Same as with facebook login
@IBAction func fbLoginClicked(_ sender: AnyObject) {
let app = UIApplication.shared.delegate as! AppDelegate
app.fbLoginManager = FBSDKLoginManager()
app.fbLoginManager.logOut()
app.fbLoginManager.loginBehavior = FBSDKLoginBehavior.native
app.fbLoginManager.logIn(withReadPermissions: ["email"], from: self, handler: { (result, error) -> Void in
if error != nil {
print(error?.localizedDescription)
} else {
if (result! as FBSDKLoginManagerLoginResult).isCancelled == true {
} else {
self.fetchFacebookUserDetail()
}
}
})
}
Here also I have removed type specification of result
and error
and problem solved. And followed this in whole app and it worked. I can run the project without error and also it is working. Thanks.
Solution 2
For facebook - the problem is in new Swift rules about converting objective-c function parameters into Swift.
Previously, if parameters in objective-c code did not have nullability attributes(like nonnull
or nullable
), Swift converts it with !
making them non optional(forced unwrapping). Now it convert it with ?
making them optional. That why you are getting an error. Before you were putting as a callback for login:
(FBSDKLoginManagerLoginResult!, NSError!) -> Void
Now you need to put:
(FBSDKLoginManagerLoginResult?, Error?) -> Void
Also, as you see, now you will not see NSError
class. Instead of that Swift will put Error
.This is also new rule. Now all "NS" prefixed in class names is removed in Swift(NSObject
-> Object
; NSError
-> Error
).
Example of working code for facebook login in Swift 3.0:
let manager = FBSDKLoginManager()
manager.logIn(withReadPermissions: ["public_profile"], from: self.controller) {
(loginResult: FBSDKLoginManagerLoginResult?, error: Error?) in
}
Example of working code for facebook request in Swift 3.0:
let request = FBSDKGraphRequest()
request.start {
(connection: FBSDKGraphRequestConnection?, result: Any?, error: Error?) in
}
As you see, now it is using Any
type instead of objective-c id
. In Swift 2.2 it was using AnyObject
. It is also new Swift converting rule.
You do not need to specify callback parameters type. I did that in code for highlighting their real types. So you can just write code without them:
let manager = FBSDKLoginManager()
manager.logIn(withReadPermissions: ["public_profile"], from: self.controller) { (loginResult, error) in }
let request = FBSDKGraphRequest()
request.start { (connection, result, error) in }
But you need to remember that they are optional now.
In conclusion some converting rules that may affect you callback code:
- Closure parameters are optional if in objective-c are not specified nullability attributes
- All "NS" prefixes is removed for objective-c classes in Swift
- If objective-c function had
id
parameter, in Swift 3.0 it will have typeAny
instead ofAnyObject
Related videos on Youtube
Max
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.
Updated on July 09, 2022Comments
-
Max almost 2 years
I have working project in Xcode 7.3 with swift 2.2 version. Now I have updated Xcode 8 and migrated to swift 3. Now my project contains errors specially for blocks like success block of afnetworking.
Which gives error as
Cannot convert value of type '() -> ()' to expected argument type '((URLSessionDataTask, Any?) -> Void)?'
I don't understand how to solve this to work as per swift 3.
And there is also same like error in Facebook login.
Which gives error as
Cannot convert value of type '(FBSDKLoginManagerLoginResult!, NSError!) -> Void' to expected argument type 'FBSDKLoginManagerRequestTokenHandler!'
and
Cannot convert value of type '(_, _, NSError!) -> Void' to expected argument type 'FBSDKGraphRequestHandler!'
This all errors are related to handler blocks in swift 3. I don't understand the errors and so that can't able to solve. Any help will be appreciated. Thanks in advance.
-
Vasyl Khmil over 7 years@Max see code example from my project that is working. I put there also the definition of callback parameters type to show what exactly it is, but it is non necessary.
-
Max over 7 yearsYes I have put same like yours then also error is there. Then I have removed :FBSDKLoginManagerLoginResult? and :Error? then error gone.
-
Vasyl Khmil over 7 years@Max try to clean the project. It should work. If no, just check by your self what kind of params it need.
-
Max over 7 yearsTrying all the possibilities and solving one by one, There are lots of syntax changes.
-
Vasyl Khmil over 7 years@Max have you managed to solve problem with facebook by changing params to optional?
-
Max over 7 yearsJust removed that optional?. Like - handler: { (result, error) -> Void in
-
Lena Bru over 7 yearsHalf of your answer helped me VERY much. I was hoping you could help me complete the other half. I have a delegate method that accepts an NSError from objective c, but when I convert it to swift, I cant figure out the syntax, it complains that my class doesnt conform to the protocol it came from...
-
Max over 7 years@LenaBru Because NSError becomes Error in swift 3, so change your method accordingly.
-
Lena Bru over 7 yearsto get the userInfo member, I have to cast it "as! NSError" ... this is so horrible...
-
Max over 7 years@LenaBru. I have faced same. I also need userInfo from NSError because I got response in json from server with error code 400 and json but I can't get those information now by this methods. So I have changed afnetworking to alamofire now.
-
Nikola Lukic over 7 yearsI need help : i always get a loginResult?.isCancelled ?
-
Max over 7 years@NikolaLukic Post a question which shows code what you have done so that you get help to find problem and it's appropriate solution.
-
Nikola Lukic over 7 years@Max Here is : stackoverflow.com/questions/39506833/… i post github project also .
-
felixwcf over 7 yearsI'm getting warning of "Expression of type 'URLSessionDataTask?' is unused". Can anyone help?
-
Max over 7 years@Felix just replace dataTask object with _ (underscore)
-
felixwcf over 7 yearsFixed by adding .resume(). My mistake. Mine is GET request.