Swift - 使用未解析的标识符'self' - 来自类中的Closure

Die*_*sel 6 swift

我试图从我的类中声明的闭包中引用我的类中的属性.我无法从我的闭包中访问self,而且我假设self会在我的闭包内引用Class API.

我想声明一个闭包,我稍后将其用作传递给URLSession dataTask的参数(它没有一个错误行).我收到标题中列出的错误.

使用未解析的标识符"self"

我现在已经写了一整天了,我只是想把它作为一个沙箱,所以我完全期待一些批评.

class Api {

    struct Location {
        var name = String()
        var author = String()
        var averageRating: String?
        var id = Int()
        var lat = Double()
        var lon = Double()
        var type = String()
    }

    var locations = [Location]()

    var doSomething = {(data: Data?, response: URLResponse?, error: Error?) -> Void in
        if error != nil {
            print(error!.localizedDescription)
        } else {
            do {
                if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
                    let myResult = json["results"] as! [[String: Any]]
                    var location : Location! = Location()
                    for jsonLocation in myResult {
                        if let name = jsonLocation["name"]{location.name = name as! String}
                        if let author = jsonLocation["author"]{location.author = author as! String}
                        if let id = jsonLocation["id"]{location.id = id as! Int}
                        if let lat = jsonLocation["lat"]{location.lat = lat as! Double}
                        if let lon = jsonLocation["lon"]{location.lon = lon as! Double}
                        if let type = jsonLocation["type"]{location.type = type as! String}

                        //ERROR IS HERE, Why does self not reference class API?
                        self.locations.append(location)
                    }
                }
            } catch {
                print("error in JSONSerialization")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现了这个,但这个例子不同,所以我不确定它是不是同一个bug或我不理解swift.

Jef*_*ton 13

拉胡尔的解释是正确的,但建议的答案是如此略微不完整.

这是一个完整的解决方案:

  1. 按照Rahul的建议宣布该doSomething物业lazy.惰性存储属性是一个属性,其初始值在第一次使用之前不会计算.换句话说,在运行时调用doSomething属性之前,不会评估此闭包,此时self保证存在此属性.有关更多详细信息,请参阅Swift编程语言中的Lazy Stored Properties.

  2. doSomething属性添加一个类型注释,这样编译器就不必在编译时推断出类型,显然它不能做,因为闭包包括self.有关详细信息,请参阅Swift编程语言中的类型安全和类型推断.

所以完整的声明是:

...
lazy var doSomething: (Data?, URLResponse?, Error?) -> Void = { (data: Data?, response: URLResponse?, error: Error?) -> Void in
...
Run Code Online (Sandbox Code Playgroud)

PS.欢迎来到Swift编程!这是一种很棒的语言,非常有趣.我希望你能像我一样享受它.


Rah*_*hul 6

您无法访问,self因为当您在闭包内部调用时它不可用,因为初始化尚未发生,因此编译器给了您错误。

修复将针对用户lazyvar,因为这将推迟self调用,因为只有在初始化之后才会调用惰性 var。

 lazy var doSomething = { your closure goes here }
Run Code Online (Sandbox Code Playgroud)