Ошибка обработчика завершения в быстрых 3 и Xcode 8
У меня есть рабочий проект в Xcode 7.3 с быстрой версией 2.2. Теперь я обновил Xcode 8 и перешел на быстрый 3. Теперь мой проект содержит ошибки специально для блоков, таких как блок успеха afnetworking.
![Снимок для ошибки в методе postnetworking post]()
Что дает ошибку как
Cannot convert value of type '() -> ()' to expected argument type '((URLSessionDataTask, Any?) -> Void)?'
Я не понимаю, как это решить, чтобы работать как быстро.
И есть также такая же ошибка при входе в Facebook.
![Ошибка входа в систему Facebook]()
Что дает ошибку как
Cannot convert value of type '(FBSDKLoginManagerLoginResult!, NSError!) -> Void' to expected argument type 'FBSDKLoginManagerRequestTokenHandler!'
и
Cannot convert value of type '(_, _, NSError!) -> Void' to expected argument type 'FBSDKGraphRequestHandler!'
Все ошибки связаны с блоками обработчика в swift 3. Я не понимаю ошибки и поэтому не могу их решить. Любая помощь будет оценена. Спасибо заранее.
Ответы
Ответ 1
Хотя я не знал об ошибке до того, что Xcode хочет сообщить мне об ошибке, но я удалил спецификацию типа с объектом и работал.
Как
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)
}
}
})
Здесь в отношении ошибки вопроса указывается в dataTask
и responseObj
, которые указаны с указанным типом. После удаления типа он работал нормально.
То же, что и при входе в facebook
@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()
}
}
})
}
Здесь также я удалил спецификацию типа result
и error
и проблема решена. И последовал за этим в целом приложении, и это сработало. Я могу запустить проект без ошибок, а также работать. Спасибо.
Ответ 2
Для facebook - проблема заключается в новых правилах Swift о преобразовании параметров функции objective-c в Swift.
Ранее, если параметры в коде objective-c не имели атрибутов нулевой видимости (например, nonnull
или nullable
), Swift преобразует его с помощью !
, делая их необязательными (принудительное разворачивание). Теперь он преобразует его с помощью ?
, делая их необязательными. Вот почему вы получаете ошибку. Перед тем, как отправить запрос для входа в систему:
(FBSDKLoginManagerLoginResult!, NSError!) -> Void
Теперь вам нужно поставить:
(FBSDKLoginManagerLoginResult?, Error?) -> Void
Кроме того, как вы видите, теперь вы не увидите класс NSError
. Вместо этого Swift поместит Error
. Это также новое правило. Теперь все "NS", префиксные в именах классов, удаляются в Swift (NSObject
→ Object
; NSError
→ Error
).
Пример рабочего кода для входа в facebook в Swift 3.0:
let manager = FBSDKLoginManager()
manager.logIn(withReadPermissions: ["public_profile"], from: self.controller) {
(loginResult: FBSDKLoginManagerLoginResult?, error: Error?) in
}
Пример рабочего кода для запроса facebook в Swift 3.0:
let request = FBSDKGraphRequest()
request.start {
(connection: FBSDKGraphRequestConnection?, result: Any?, error: Error?) in
}
Как вы видите, теперь он использует тип Any
вместо objective-c id
. В Swift 2.2 он использовал AnyObject
. Это также новое правило преобразования Swift.
Вам не нужно указывать тип параметров обратного вызова. Я сделал это в коде, чтобы выделить их реальные типы. Таким образом, вы можете просто написать код без них:
let manager = FBSDKLoginManager()
manager.logIn(withReadPermissions: ["public_profile"], from: self.controller) { (loginResult, error) in }
let request = FBSDKGraphRequest()
request.start { (connection, result, error) in }
Но вы должны помнить, что теперь они являются необязательными.
В заключение некоторые правила преобразования, которые могут повлиять на ваш код обратного вызова:
- Параметры закрытия необязательны, если в objective-c не указаны атрибуты недействительности
- Все префиксы "NS" удаляются для классов objective-c в Swift
- Если функция objective-c имела параметр
id
, в Swift 3.0 он будет иметь тип Any
вместо AnyObject