Reputation: 501
I got a method which works like a refresher which uses the GCD pattern as shown below:
func getStepsForTheWeek() {
let concurrentQueue : dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(concurrentQueue, {
// Create an array of Days.
var days = [Day]()
dispatch_sync(concurrentQueue, {
print("first")
for day in 0...7 {
let date = self.getDate(day)
// Get the date the day after that day.
let endDate = self.getDateDayAfter(date)
// Create a Day.
var day = Day(date: date)
self.pedometer.queryPedometerDataFromDate(date, toDate: endDate, withHandler: {numberOfSteps, error in
print("fetching")
if error != nil {
print("There was an error requesting data from the pedometer: \(error)")
} else {
day.steps = numberOfSteps!.numberOfSteps as Int
days.append(day)
}
})
}
})
dispatch_sync(dispatch_get_main_queue(), {
print("second")
self.historyViewController.days = days
self.historyViewController.reloadHistory()
})
})
}
When the app starts the method works as it is intended to. But when the app is in the background and when I'm going back to the app I got this Observer which calls the method again to refresh its content.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "appBecomeActive", name: UIApplicationWillEnterForegroundNotification, object: nil )
But everytime I do this the second code-block is running before the first one. Any help?
Upvotes: 0
Views: 128
Reputation: 501
I solve it. In the query I check if the array of days is filled (e.g size of 8). When filled the reload should be done. I also deleted all unnecessary sync-tasks. Much cleaner now. It was simpler than I thought.
func getStepsForTheWeek() {
// Create an array of Days.
var days = [Day]()
print("first")
// Fetch the total steps per day for 8 days (0 - 7).
for day in 0...7 {
// Get days date from today.
let date = self.getDate(day)
// Get the date the day after that day.
let endDate = self.getDateDayAfter(date)
// Create a Day.
var day = Day(date: date)
// Query the Pedometer for the total steps of that day.
self.pedometer.queryPedometerDataFromDate(date, toDate: endDate) {
(data, error) -> Void in
if(error == nil){
print("fetching")
day.steps = data!.numberOfSteps as Int
days.append(day)
if(days.count == 8){
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("finished")
self.historyViewController.days = days
self.historyViewController.reloadHistory()
})
}
}
}
}
}
Thanks to Fonix and gnasher729.
Upvotes: 0
Reputation: 11597
i think you should do the UI update in the completion handler of the pedometer query
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
self.pedometer.queryPedometerDataFromDate(date, toDate: endDate, withHandler: { numberOfSteps, error in
if error != nil {
print("There was an error requesting data from the pedometer: \(error)")
} else {
let numberOfStepsThisDay = numberOfSteps?.numberOfSteps as! Int
day.steps = numberOfStepsThisDay
days.append(day)
}
dispatch_async(dispatch_get_main_queue(), {
self.historyViewController.days = self.days
self.historyViewController.reloadHistory()
})
})
})
you should always update the UI in the completion handler of the method if it has one, since you dont know whether it could be asynchronous or not (usually would be asynchronous if using a completion handler), you can probably drop the outer dispatch_async if there is no other code in it besides the pedometer query
Upvotes: 1