Pak Ho Cheung Pak Ho Cheung - 3 months ago 70
Swift Question

dispatch_async vs dispatch_sync in fetch data. Swift

After reading so many posts about parallel and concurrent, I still confuse what is the proper way to fetch data. For example, in my project, I have a button for user to fetch data. My code is something like below.

var array = [Int]()
func fetchData() {

....
....
response(objects: [object], error: NSError?) {
for object in objects {
array.append(object.number) // assume object.number return an Int
}

// confuse here. Should I use async here because I am worry if the user
// click the fetchData button more than one time, the append and make
// function will be happened at the same time. Or, is there anything I
// made a wrong assumption? I guess I need a serial operation. Correct?

dispatch_async(dispatch_get_main_queue()) {
makeCollectionView() // using the data in array
}
}
}

Answer

GCD provides queues for executing tasks. Queues can be of two types – concurrent or serial. In serial queue tasks execute one at time (in FIFO order), in concurrent queue several tasks at time.

To prevent user fetch data while one fetch task is running, it is needed to not submit fetch task to queue at this moment. No matter what kind of queue is it – concurrent or serial.

var array = [Int]()
var isFethingData = false

func fetchData() {
    if !isFethingData {
        isFethingData = true
        dispatch_async(queueForFetchData) {
            …
            response(objects: [object], error: NSError?) {
                for object in objects {
                    array.append(object.number)
                }

                dispatch_async(dispatch_get_main_queue()) {
                    makeCollectionView()
                }
                isFethingData = false
            }
    }
}

dispatch_async and dispatch_sync is functions which submits tasks to queue. The difference is that dispatch_async return immediately after task has been submitted, but dispatch_sync wait until task complete. For example:

print("\(NSDate()) qq")
dispatch_sync(queue) {
    // … some code which runs for 10 minutes.
    print("\(NSDate()) ee")
}
print("\(NSDate()) ww")
// 2016-08-18 16:02:00 qq
// 2016-08-18 16:12:00 ee
// 2016-08-18 16:12:00 ww


print("\(NSDate()) qq")
dispatch_async(queue) {
    // … some code which runs for 10 minutes.
    print("\(NSDate()) ee")
}
print("\(NSDate()) ww")
// 2016-08-18 16:02:00 qq
// 2016-08-18 16:02:00 ww
// 2016-08-18 16:12:00 ee