Void函数中意外的非Void返回值(Swift 2.0)

Void函数中意外的非Void返回值(Swift 2.0),swift,closures,nsurlsession,Swift,Closures,Nsurlsession,我一直在浏览StackOverflow的问题,试图找出我的代码哪里出了问题,但我就是不知道!我试图将我的Swift 1.2项目转换为Swift 2.0,但我的类在下载JSON数据时遇到了问题 我在void函数中不断收到错误意外的非void返回值 这是我正在使用的代码,有点被截断了 ... class func fetchMinionData() -> [Minion] { var myURL = "http://myurl/test.json" let dataURL

我一直在浏览StackOverflow的问题,试图找出我的代码哪里出了问题,但我就是不知道!我试图将我的Swift 1.2项目转换为Swift 2.0,但我的类在下载JSON数据时遇到了问题

我在void函数中不断收到错误意外的非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()
}

...

也许我忽略了一些简单的东西,但我不确定为什么我的函数会被认为是空的。任何想法都将不胜感激!谢谢大家!

您遇到问题,因为您的线路:

return minions
不会从函数返回。相反,它从
dataTaskWithRequest
中的完成处理程序返回。它不应该这样做,因为闭包是一个空函数

您遇到的问题是由于
dataTaskWithRequest
是一个异步操作。这意味着它可以在执行函数后返回

因此,您需要更改您的设计模式

其中一种方法是:

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
。只有在收到通知后,您才应该像抓取仆从一样处理他们。

您遇到了问题,因为您的线路:

return minions
不会从函数返回。相反,它从
dataTaskWithRequest
中的完成处理程序返回。它不应该这样做,因为闭包是一个空函数

您遇到的问题是由于
dataTaskWithRequest
是一个异步操作。这意味着它可以在执行函数后返回

因此,您需要更改您的设计模式

其中一种方法是:

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
。只有在你收到通知后,你才应该像抓取仆从一样处理他们。

我通过创建一个完成处理程序修复了我的问题。您可以这样做,而不是使用通知:

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

我通过创建一个完成处理程序修复了我的问题。您可以这样做,而不是使用通知:

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

这对我来说是有道理的。但是如果我将
return minions
行移动到after
}.resume()
,我认为它应该去那里,我会收到未解析标识符minion的错误使用。我似乎不知道该怎么解决!现在对我来说有意义了!谢谢你,安德烈!感谢@AndriyGordiychuk Gordiychuk提供的非常重要的一行,您遇到了一个问题,因为您的行:返回仆从不会从您的函数返回。相反,它从DataTaskWithRequest中的完成处理程序返回,这对我来说是有意义的。但是如果我将
return minions
行移动到after
}.resume()
,我认为它应该去那里,我会收到未解析标识符minion的错误使用。我似乎不知道该怎么解决!现在对我来说有意义了!谢谢你,安德烈!感谢@AndriyGordiychuk Gordiychuk提供的非常重要的一行,您遇到了一个问题,因为您的行:返回仆从不会从您的函数返回。相反,它从dataTaskWithRequestWay中的完成处理程序返回,以恢复4年前的答案,但我们是否必须进行闭包
@escaping
,因为函数作用域将在异步调用之前完成?恢复4年前的答案的方法,但是我们不需要进行闭包
@escaping
,因为函数作用域将在异步调用之前完成吗?