0

well, I am just about to turn crazy. I am a swift beginner with quite a big programming action going on and it is getting a bit overwhelming. Maybe you can assist.

func getDataFromDatamanager() {
    DataManager.getGoldPriceFromQuandlWithSuccess { (QuandlGoldPrice) -> Void in
        let json = JSON(data: QuandlGoldPrice)
        if let datasetMineral = json["dataset"]["dataset_code"].string {
            print("NSURLSession: \(datasetMineral)")
        }
    DataManager.getSilverPriceFromQuandlWithSuccess { (QuandlSilverPrice) -> Void in
        let json = JSON(data: QuandlSilverPrice)
        if let datasetMineral = json["dataset"]["dataset_code"].string {
            print("NSURLSession: \(datasetMineral)")
        }
}

There are about 15 other calls in this function and they all need a different time to download. I am calling the function to operate on the main thread and to start an activity Indicator:

dispatch_async(dispatch_get_main_queue(), {
        self.activityIndicator.startAnimating()
        self.getDataFromDatamanager()
    })

My question: How can I stop the activity Indicator only once all functions are downloaded?

kangarooChris
  • 718
  • 1
  • 10
  • 21
  • Track the current downloads and stop the activity indicator when the number drops to zero. – dasdom Mar 17 '16 at 06:23
  • You can also use dispatch groups. Refer to this: http://stackoverflow.com/questions/11909629/waiting-until-two-async-blocks-are-executed-before-starting-another-block – Santhosh Mar 17 '16 at 06:46

1 Answers1

1

Introduce completedItems: variable. You can increase that when the download complete for some function. after every completion calls the stop activity function, like this :-

var completedItems:Int = 0

func getDataFromDatamanager() {
DataManager.getGoldPriceFromQuandlWithSuccess { (QuandlGoldPrice) -> Void in
    let json = JSON(data: QuandlGoldPrice)
    if let datasetMineral = json["dataset"]["dataset_code"].string {
        completedItems = completedItems + 1 // completedItems ++
        stopActivity()
        print("NSURLSession: \(datasetMineral)")
    }
DataManager.getSilverPriceFromQuandlWithSuccess { (QuandlSilverPrice) -> Void in
    let json = JSON(data: QuandlSilverPrice)
    if let datasetMineral = json["dataset"]["dataset_code"].string {
        completedItems = completedItems + 1 // completedItems ++
        stopActivity()
        print("NSURLSession: \(datasetMineral)")
    }

}

func stopActivity() {
     if completedItems == 15  { // give # of functions
        dispatch_sync(dispatch_get_main_queue(), {
            self.activityIndicator.stopAnimating()
        })
      }
}
Mudith Chathuranga Silva
  • 7,253
  • 2
  • 50
  • 58
  • Great stuff, thanks for that!. I did have to change the stopActivity() function to this: func stopActivity() { if completedItems == 10 { // give # of functions dispatch_async(dispatch_get_main_queue(), { self.activityIndicator.stopAnimating() }) } } – kangarooChris Mar 17 '16 at 09:43
  • BTW ui modification should done on main thread , not async, should correct it as sync – Mudith Chathuranga Silva Mar 17 '16 at 09:44
  • Hi, thanks for the comment - can you please add code to your suggestion about main thread? – kangarooChris Mar 17 '16 at 11:56
  • @kangarooChris Unfortunately, this solution is not thread safe: accessing the variable `completedItems` may happen on different threads (unless all completion handlers will execute on the same thread and this thread is also the caller's one). You might get sporadic errors whose effect is undefined. Solutions which are correct would either utilise dispatch groups, atomic operations, or use a dedicated "execution context" (a dedicated dispatch queue, or thread) where the shared variable will be accessed. – CouchDeveloper Mar 18 '16 at 10:27