ah_gel
ah_gel

Reputation: 411

Store value from escaping closure

I am having issue with storing the value from a escaping closure.

Basically I have a get request function with a escaping completionHandler. The signature looks like this:

struct NetworkRequest {

   func getRequest(completionHandler: @escaping (_ result: [String)]?) -> Void) {
   // implementations
   }
}

Now I have a struct that calls this method. Something like this:

struct foo {

   var value: [String]?
   lazy var networkRequest = NetworkRequest()

   func testGet() {
      networkRequest.getRequest((result) {
         self.value = result  // here's my issue
      }
   }
}

I am getting this "Closure cannot implicitly capture a mutating self parameter" error

I need to store the result value but I couldn't. How do I resolve this issue?

Upvotes: 1

Views: 277

Answers (1)

Vlad Papko
Vlad Papko

Reputation: 13302

The behavior you are trying to achieve by using structs isn't possible in Swift 3. I would suggest to make foo a class instead of struct.
This will work if using struct isn't critical for you.

Here is updated code:

struct NetworkRequest {

    func getRequest(completionHandler: @escaping ([String]?) -> Void) {
        // implementations
    }
}

class foo {

    var value: [String]?
    lazy var networkRequest = NetworkRequest()

    func testGet() {
        networkRequest.getRequest { result in
            self.value = result
        }
    }
}

The reason why your code can not be complied is the copy by value nature of structs:
In your example getRequest has @escaping closure completionHandler and struct foo tries to modify itself inside this closure implementation. But to be sure that self exists at the moment when completionHandleris called compiler needs to copy self. In structs copy means creating new instance. That means in self.value = result self is new instance of foo struct. And modifying this new instance doesn't make any sense because you as consumer of this struct will never get this new instance.
It works with classes because they copy by reference. That means in self.value = result self is the same instance as before.

Upvotes: 3

Related Questions