Lance Samaria
Lance Samaria

Reputation: 19592

Swift Closure Expression

I have to download some names into an array but I don't know exactly how many names will get downloaded. Only after all the names are downloaded I need a custom function to run.

I used a closure to call the custom function but what happens is once the first name is downloaded, my custom function is getting called immediately, then the second name is downloaded, then the custom function is called again etc.

I need the custom function to get called only after all the names are downloaded into the array, not after each name is downloaded. Where am I doing something wrong at?

This is what I'm getting:

Mable
This should only print once not three times
Marlene
This should only print once not three times
Moses
This should only print once not three times

This is what I want:

Mable
Marlene
Moses
This should only print once not three times

If possible, i would like the issue to be resolved inside: addAllNamesToArrayThenRunClosure

Code:

//There actually can be 1 or 100 names but I just used 3 for the example
var randomNames = ["Mable", "Marlene", "Moses"]
var nameArray = [String]()

func addAllNamesToArrayThenRunClosure(name: String, completionHandler: (success:Bool)->()){
    nameArray.append(name)
    print(name)

    let flag = true
    completionHandler(success:flag)
}

func customFunction(){
    print("This should only print once not three times")
}

for name in randomNames{
    addAllNamesToArrayThenRunClosure(name){

      //Shouldn't this run only after the array is filled?
      (success) in
      if success == true{
          customFunction()
      }
    }
}

Upvotes: 0

Views: 68

Answers (2)

Nick Kohrn
Nick Kohrn

Reputation: 6049

I suggest adding the for loop in the addAllNamesToArrayThenRunClosure method. Then, you can call the completion handler after all names have been added.

var randomNames = ["Mable", "Marlene", "Moses"]
var nameArray = [String]()

func addAllNamesToArrayThenRunClosure(completionHandler: (success: Bool) -> ()) {
    for name in randomNames {
        nameArray.append(name)
    }
    completionHandler(true)
}

Then, call your custom function from the completion handler like so:

addAllNamesToArrayThenRunClosure() { success in
    self.customFunction()
}

Upvotes: 1

Alexander
Alexander

Reputation: 63271

addAllNamesToArrayThenRunClosure actually only adds a single name, and you call it once per name. If you call your completion handler in there, it'll be called ... once per name. You need to redesign this so the closure is called after all the names are added.

Here's how I would do it:

//There actually can be 1 or 100 names but I just used 3 for the example
var randomNames = ["Mable", "Marlene", "Moses"]
var globalNames = [String]()

func add(names: [String], completionHandler: ( _ success: Bool) -> Void) {
    globalNames.append(contentsOf: names)

    completionHandler(true)
}

add(names: randomNames) { success in
    if success {
        print("Finished")
    }
}

Upvotes: 1

Related Questions