web-dev-qa-db-fra.com

Valeur de retour non nulle inattendue dans Void Function (Swift 2.0)

J'ai parcouru les questions de StackOverflow pour essayer de comprendre où je me trompe avec mon code, mais je n'arrive tout simplement pas à le faire! J'essaie de convertir mon Swift 1.2 en Swift 2.0) et je rencontre un problème avec ma classe qui télécharge des données JSON.

Je reçois continuellement l'erreur valeur de retour non vide inattendue dans la fonction void.

Voici le code, quelque peu tronqué, que j'utilise;

...

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

...

J'ai peut-être oublié quelque chose de simple, mais je ne sais pas pourquoi ma fonction serait considérée comme nulle. Toute pensée serait immensément appréciée! Merci!

38
ZbadhabitZ

Vous avez un problème parce que votre ligne:

return minions

ne revient pas de votre fonction. Au lieu de cela, il retourne du gestionnaire d'achèvement dans dataTaskWithRequest. Et cela ne devrait pas être le cas, car cette fermeture est une fonction vide.

Le problème que vous rencontrez provient du fait que dataTaskWithRequest est une opération asynchrone. Ce qui signifie qu'il peut revenir plus tard après avoir exécuté votre fonction.

Donc, vous devez changer votre modèle de conception.

Une façon de faire serait la suivante:

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

Ensuite, avant d'appeler votre fonction, vous devez vous enregistrer pour écouter NSNotification avec le nom "minionsFetched". Et seulement après avoir reçu cette notification, vous devriez traiter les sbires comme s'ils avaient été récupérés.

55
Andriy Gordiychuk

J'ai corrigé le mien en créant un gestionnaire d'achèvement. Vous pouvez le faire au lieu d'utiliser des notifications:

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