Swift中的Grand Central Dispatch只适用于第一次运行



我得到了一个类似于刷新器的方法,它使用如下所示的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()
        })
    })
}

当应用程序启动时,该方法按预期工作。但当应用程序在后台时,当我回到应用程序时,我得到了这个Observer,它再次调用该方法来刷新其内容。

        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和咬牙切齿729。

最新更新