Swift 3和Xcode 8中完成处理程序的错误

18

我的Xcode工程在Swift 2.2版本下运作良好。现在我已经升级到Xcode 8并转换到Swift 3。现在我的项目包含特别是在afnetworking的成功块之类的区块方面出现了错误。

afnetworking post方法错误的快照

这会导致错误:

Cannot convert value of type '() -> ()' to expected argument type '((URLSessionDataTask, Any?) -> Void)?'

我不明白如何将其更改以适用于Swift 3。

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中的处理程序块相关。我不理解这些错误,因此无法解决。任何帮助将不胜感激。提前致谢。

2个回答

14

对于Facebook而言,问题出在新的Swift规则上,该规则涉及将Objective-C函数参数转换为Swift。

以前,在Objective-C代码中,如果参数没有空值属性(如nonnullnullable),Swift会使用!将其转换为非可选类型(强制解包)。现在它使用?将其转换为可选类型。这就是为什么您会收到错误信息。在此之前,您将其作为登录回调函数:

(FBSDKLoginManagerLoginResult!, NSError!) -> Void

现在你需要放置:

(FBSDKLoginManagerLoginResult?, Error?) -> Void

同时你会注意到,现在你将不会看到 NSError 类了。取而代之的是Swift会用 Error 。这也是新规则。现在所有类名中以 "NS" 为前缀的部分都被删除了(例如:NSObject -> Object; NSError -> Error)。

以下是在 Swift 3.0 中使用 Facebook 登录的代码示例:

let manager = FBSDKLoginManager()

manager.logIn(withReadPermissions: ["public_profile"], from: self.controller) {
    (loginResult: FBSDKLoginManagerLoginResult?, error: Error?) in

}

Swift 3.0实现facebook请求的可运行代码示例:

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 }

但是你需要记住,现在它们是可选的。

总之,以下是一些可能会影响您回调代码的转换规则:

  1. 如果在 Objective-C 中未指定空值属性,则闭包参数是可选的。
  2. 在 Swift 中,所有 "NS" 前缀都被移除了。
  3. 如果 Objective-C 函数有 id 参数,在 Swift 3.0 中它将使用 Any 类型而不是 AnyObject 类型。

@Max,请看一下我的项目中的代码示例,它是可行的。我还在那里放置了回调参数类型的定义,以展示它到底是什么,但这并非必要。 - Vasyl Khmil
是的,我已经像你一样放置了相同的内容,但仍然出现错误。然后我删除了:FBSDKLoginManagerLoginResult?和:Error?然后错误消失了。 - Max
@Max 尝试清理项目。它应该可以工作。如果不能,请自己检查需要哪些参数。 - Vasyl Khmil
尝试所有可能性并逐一解决,这会有很多语法变化。 - Max
@Max,你通过将参数更改为可选项解决了与Facebook的问题吗? - Vasyl Khmil
刚刚移除了那个可选项?像这样 - handler: { (result, error) -> Void in - Max

13

虽然我之前不知道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)
                    }


                }

        })

关于问题,出现在dataTaskresponseObj中,它们都有指定类型。移除类型后,问题得到解决。

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()
                }
            }
        })

    }

这里我删除了resulterror的类型规定,问题得到解决。在整个应用程序中都采用了这种方法,也成功了。谢谢。


我需要帮助:我总是得到一个loginResult?.isCancelled?的结果。 - Nikola Lukic
@NikolaLukic 发布一个包含你已经编写的代码的问题,以便获得帮助找到问题并得到适当的解决方案。 - Max
@Max,这是一个关于Facebook登录在Xcode8和Swift3中无法工作的问题。我在stackoverflow上发布了相关问题,并附带了Github项目链接。 - Nikola Lukic
1
@Felix 只需将 dataTask 对象替换为 _ (下划线)。 - Max
通过添加.resume()修复。是我的错误。我的请求方式是GET。 - felixwcf
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接