Swift 中的 Grand Central Dispatch 仅适用于第一个 运行
Grand Central Dispatch in Swift only works the first run
我得到了一种使用 GCD 模式的复习方法,如下所示:
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()
})
})
}
当应用程序启动时,该方法会按预期运行。
但是当应用程序在后台并且当我返回应用程序时,我得到了这个观察者,它再次调用该方法来刷新它的内容。
NSNotificationCenter.defaultCenter().addObserver(self, selector: "appBecomeActive", name: UIApplicationWillEnterForegroundNotification, object: nil )
但每次我这样做时,第二个代码块都在第一个代码块之前 运行。
有帮助吗?
我认为你应该在计步器查询的完成处理程序中进行 UI 更新
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()
})
})
})
你应该总是在方法的完成处理程序中更新 UI 如果它有一个,因为你不知道它是否可以是异步的(如果使用完成处理程序通常是异步的),如果除了计步器查询
之外没有其他代码,您可以删除外部 dispatch_async
我解决了。
在查询中,我检查天数数组是否已填满(例如大小为 8)。
装满后应该重新加载。我还删除了所有不必要的同步任务。现在干净多了。比我想象的要简单。
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()
})
}
}
}
}
}
感谢 Fonix 和 gnasher729。
我得到了一种使用 GCD 模式的复习方法,如下所示:
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()
})
})
}
当应用程序启动时,该方法会按预期运行。 但是当应用程序在后台并且当我返回应用程序时,我得到了这个观察者,它再次调用该方法来刷新它的内容。
NSNotificationCenter.defaultCenter().addObserver(self, selector: "appBecomeActive", name: UIApplicationWillEnterForegroundNotification, object: nil )
但每次我这样做时,第二个代码块都在第一个代码块之前 运行。 有帮助吗?
我认为你应该在计步器查询的完成处理程序中进行 UI 更新
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()
})
})
})
你应该总是在方法的完成处理程序中更新 UI 如果它有一个,因为你不知道它是否可以是异步的(如果使用完成处理程序通常是异步的),如果除了计步器查询
之外没有其他代码,您可以删除外部 dispatch_async我解决了。 在查询中,我检查天数数组是否已填满(例如大小为 8)。 装满后应该重新加载。我还删除了所有不必要的同步任务。现在干净多了。比我想象的要简单。
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()
})
}
}
}
}
}
感谢 Fonix 和 gnasher729。