web-dev-qa-db-ja.com

予期しない非void戻り値In Void Function(Swift 2.0)

私は自分のコードのどこに問題があるのか​​を把握しようとしてStackOverflowの質問をざっと読んでいますが、私にはわかりません! Swift 1.2プロジェクトをSwift 2.0に変換しようとしていますが、JSONデータをダウンロードするクラスに問題があります。

エラーvoid関数の予期しないnon-void戻り値が常に表示されます。

以下は、私が使用しているコードの一部を切り捨てたものです。

...

class func fetchMinionData() -> [Minion] {

    var myURL = "http://myurl/test.json"

    let dataURL = NSURL(string: myURL)

    let request = NSURLRequest(URL: dataURL!, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5.0)

    let session = NSURLSession.sharedSession()

    session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
        let minionJSON = JSON(data!)

        var minions = [Minion]()

        for (_, minionDictionary) in minionJSON {
            minions.append(Minion(minionDetails: minionDictionary))
        }

        return minions
        //THIS IS WHERE THE ERROR OCCURS

    }).resume()
}

...

おそらく私は単純なものを見落としているかもしれませんが、なぜ私の機能がまったく無効であると考えられるのか分かりません。どんな考えでも大歓迎です!ありがとうございました!

38
ZbadhabitZ

あなたのラインが原因で問題があります:

return minions

関数から戻りません。代わりに、dataTaskWithRequestの完了ハンドラーから戻ります。そして、そのクロージャーは無効な関数であるため、そうすべきではありません。

dataTaskWithRequestが非同期操作であるという事実から生じる問題。つまり、関数を実行した後、後で戻ることができます。

そのため、設計パターンを変更する必要があります。

その方法の1つは次のとおりです。

static var minions:[Minion] = [] {
    didSet {
        NSNotificationCenter.defaultCenter().postNotificationName("minionsFetched", object: nil)
   }
}



class func fetchMinionData() {

    var myURL = "http://myurl/test.json"
    let dataURL = NSURL(string: myURL)
    let request = NSURLRequest(URL: dataURL!, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5.0)

    let session = NSURLSession.sharedSession()

    session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
        let minionJSON = JSON(data!)

        var minions = [Minion]()

        for (_, minionDictionary) in minionJSON {
            minions.append(Minion(minionDetails: minionDictionary))
        }

        self.minions = minions
        //THIS IS WHERE THE ERROR OCCURS

    }).resume()
}

次に、関数を呼び出す前に、「minionsFetched」という名前のNSNotificationをリッスンするように登録する必要があります。そして、その通知を受け取った後にのみ、手先を取得したかのように処理する必要があります。

55

完了ハンドラーを作成することで修正しました。通知を使用する代わりにこれを行うことができます。

class func fetchMinionData(completionHandler: (minions: [Minion]) -> Void) {

    var myURL = "http://myurl/test.json"

    let dataURL = NSURL(string: myURL)

    let request = NSURLRequest(URL: dataURL!, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5.0)

    let session = NSURLSession.sharedSession()

    session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
        let minionJSON = JSON(data!)

        var minions = [Minion]()

        for (_, minionDictionary) in minionJSON {
            minions.append(Minion(minionDetails: minionDictionary))
        }

        completionHandler(minions: minions)
        //THIS IS WHERE YOUR PREVIOUS ERROR OCCURRED

    }).resume()
}
22
jaytrixz