0

I have a Swift class Test with the following initializer.

import Foundation

class Test {
    var x: Int

    var response: [String: AnyObject]

    init(_ x: Int) {
        self.x = x

        self.response = [String: AnyObject]()

        self.y(x)
    }
}

Inside Test, I also have the following method.

func y(_ x: Int) {
    // This is a task with a completion handler of type (_, _, _) -> Void
    let ... = ...(with: ..., completionHandler: { () in
       do {
           // The type of z is [String: AnyObject]
           let z = ...
           self.response = z
       } catch {
           return
       }
   })

Calling y is supposed to reassign z to self.response, but self.response is persistently an empty dictionary.

Am I missing something?

Angelo
  • 3
  • 2
  • When your completionHandler is called async, is `self` still exists? Also, where did you check your self.response, since completionHandler is auto `escaping` – antonio081014 Feb 06 '17 at 18:34
  • Your function y is not waiting for the completion handler to finish. It returns immediately and so Test.init() completes before self.response gets set. You should also pass a weak reference to self into the completion handler. – onnoweb Feb 06 '17 at 18:48
  • @onnoweb If I change `completionHandler: { () in` to `completionHandler: { [weak self] () in` and `self.response = z` to `self?.response = z`, `self.response` is still empty. – Angelo Feb 06 '17 at 19:10
  • Yes, that's because y() doesn't wait for your completion handler to complete before it returns. The closure is an asynchronous operation. You probably want to give y() a completion handler parameter which y calls when y's completion handler gets called. – onnoweb Feb 06 '17 at 19:32

1 Answers1

0

Although this way seems like something you might want to reconsider (and I am going to point you to this nice answer on a similar question: https://stackoverflow.com/a/12797624/2617369), the way I would do it with a combo of adding a completion to your y method and with a dispatch group like this:

(This is swift 3 because I don't have a previous version IDE to show you in 2.3 but it should not be much different):

class Test {
    var x: Int

var response: [String: Any]

init(_ x: Int) {
    self.x = x

    self.response = [String: Any]()

    let group = DispatchGroup()
    group.enter()
    self.y(x) { (result) in
        self.response = result
        group.leave()
    }

    group.wait()
}

func y(_ x: Int, completion:@escaping (([String:Any])->())) {
    // This is a task with a completion handler of type (_, _, _) -> Void
    let ... = ...(with: ..., completionHandler: { () in
        do {
        // The type of z is [String: Any]
            let z = ...
            completion(z);
        } catch {
        return
        }
    }
}
Community
  • 1
  • 1
Prientus
  • 733
  • 6
  • 15