Swift - use of unresolved id "i" - from closure in class

I am trying to reference a property in my class from a closure declared in my class. I cannot access myself from my closure and I am assuming that myself will be referring to the class API from my closure.

I want to declare a closure, which I use later as a parameter to navigate to the dataSask url (it works without one line of error). I am getting the error mentioned in the title.

Using unresolved identifier 'self'

I've been writing fast all day and just trying to get my head around the sandbox, so I totally expect some criticism.

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

      

I found this one , but this example is different, so I wasn't sure if it was the same error or if I didn't understand swift.

+3


source to share


4 answers


Rahul explains the correctness, but the suggested answer is so slightly incomplete.

Here's the complete solution:

  • Declare the property doSomething

    as lazy

    Rahul suggested. A spurious stored property is a property whose initial value is not calculated until first used. In other words, this closure will not be evaluated until the doSomething property is called at runtime, after which it is guaranteed to exist self

    . See Lazy Stored Properties in Swift Programming Language for details .

  • Add a type annotation to the property doSomething

    , so the compiler doesn't need to inference the type at compile time, which it apparently cannot do, since closures include self

    . See Type Safety and Type Input in Swift for details .



So the complete declaration is:

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

      

ps. Welcome to Swift! It's a fantastic language and really fun. Hope you enjoy it the way I do.

+6


source


You cannot access self

, because it is not available when you call inside the closure, because the initialization has not been done yet and therefore the compiler is giving you an error.

The fix will be for user lazy

var, as this will postpone the call self

because lazy var is only called after initialization.



 lazy var doSomething = { your closure goes here }

      

+2


source


Replace var locations = [Location]()

with thisvar locations : [Location]?

and var location : Location! = Location()

with self.locations = [Location]()

and self.locations.append(location)

withself.locations?.append(location)

You will be good!

lazy var is too complex to understand as far as I understand, but you can use it like this:

lazy var locations:[Location] = {
        let locations = Location()
        return locations
    }()

      

0


source


I have the same questions as you and I solve it with lazy var


Here is a quick example

My original code:

class MyClass {
    let callback:()->() = {
        self.foo()   // Compile error: Use of unresolved identifier "self"
    }

    func foo() {
        print("bar")
    }
}

      

Compile the error on this line, I am using self


But I change it to

class MyClass {
    lazy var callback:()->() = {
        [unowned self] in
        self.foo()
    }

    func foo() {
        print("bar")
    }
}

let c = MyClass()
c.callback()

      

which solved the problem

Literature: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html
http://mikebuss.com/2014/06/22/lazy-initialization-swift/
Should we always use [unowned self] inside a closure in Swift

0


source







All Articles