web-dev-qa-db-ja.com

Swift 3およびXcode 8の完了ハンドラーのエラー

Xcode 7.3でSwift 2.2バージョンを使用しています。現在、Xcode 8を更新し、Swift 3.に移行しています。ネットワーキングの成功ブロックのように。

Snapshot for error in afnetworking post method

エラーは次のようになります

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

Swift 3。

また、Facebookのログインにも同じようなエラーがあります。

Facebook Login error

エラーは次のようになります

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.のハンドラーブロックに関連しています。エラーを理解していないため、解決できません。ご協力をお願いします。ありがとうございます。

18
Max

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

    }

ここでも、resulterrorの型指定を削除し、問題を解決しました。そして、アプリ全体でこれに従ったとそれは働いた。私はエラーなしでプロジェクトを実行することができ、またそれは機能しています。ありがとう。

13
Max

Facebookの場合、問題は新しいSwift Objective-c関数パラメーターのSwiftへの変換に関するルールにあります。

以前は、objective-cコードのパラメーターにnullability属性(nonnullnullableなど)がなかった場合、Swiftは!で変換します]それらはオプションではありません(強制的なアンラッピング)。それを?で変換してオプションにします。そのため、エラーが発生します。ログインのコールバックとして配置する前:

(FBSDKLoginManagerLoginResult!, NSError!) -> Void

今、あなたは置く必要があります:

(FBSDKLoginManagerLoginResult?, Error?) -> Void

また、ご覧のとおり、NSErrorクラスは表示されません。その代わりにSwiftはErrorを配置します。これも新しいルールです。クラス名のすべての"NS"はSwift(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

}

ご覧のとおり、現在、objective-c Anyの代わりに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でnullability属性が指定されていない場合、クロージャーパラメーターはオプションです
  2. すべての"NS"プレフィックスはSwiftのObjective-Cクラスから削除されます
  3. Objective-C関数にidパラメーターがあった場合、Swift 3.0では、AnyではなくAnyObject型になります。
14
Vasyl Khmil