da1lbi3
da1lbi3

Reputation: 4519

Convert swift 2.x to swift 3 problems

I have made this function to get all steps for each day but I want to convert this function from swift 2.x to swift 3. But I get stuck on 2 different points.

let anchorDate = calendar.dateComponents(anchorComponents)  

I get this error: Cannot invoke dateCompontents with an argument of list type (Datecomponents)


And on this point:

let stepsQuery = HKStatisticsCollectionQuery(quantityType: HKQuantityType, quantitySamplePredicate: nil, options: .CumulativeSum, anchorDate: anchorComponents!, intervalComponents: interval)

Error: Cannot convert value of type HKQuantityType.Type to expected argument type HKQuantityType.


The complete function:

func getDailySteps(){
            let calendar = NSCalendar.current
            let interval = NSDateComponents()
            interval.day = 1

        var anchorComponents = calendar.dateComponents([.day , .month , .year], from: NSDate() as Date)
        anchorComponents.hour = 0
        let anchorDate = calendar.dateComponents(anchorComponents)

        // Define 1-day intervals starting from 0:00
        let stepsQuery = HKStatisticsCollectionQuery(quantityType: HKQuantityType, quantitySamplePredicate: nil, options: .CumulativeSum, anchorDate: anchorComponents!, intervalComponents: interval)

        // Set the results handler
        stepsQuery.initialResultsHandler = {query, results, error in
            let endDate = NSDate()
            let startDate = calendar.dateByAddingUnit(.Day, value: -7, toDate: endDate, options: [])
            if let myResults = results{                                                                             myResults.enumerateStatisticsFromDate(startDate!, toDate: endDate) { statistics, stop in
                if let quantity = statistics.sumQuantity(){
                    let date = statistics.startDate
                    let steps = quantity.doubleValueForUnit(HKUnit.countUnit())
                    print("\(date): steps = \(steps)")
                    //NOTE: If you are going to update the UI do it in the main thread
                    dispatch_async(dispatch_get_main_queue()){
                        //update UI components
                    }

                }
                } //end block
            } //end if let
        }

        HKHealthStore?.executeQuery(stepsQuery)

    }

So how can I convert this method to swift 3 ?

Upvotes: 2

Views: 1808

Answers (2)

pfj
pfj

Reputation: 187

.dateComponents was removed as part of better translating Objective-C APIs into swift: https://github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md

Try

calendar.date(from: DateComponents)

As far as your healthkit issues, I suspect you need something more along the lines of

HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount

Rather than the entire HKQuantityType class.

Upvotes: 0

FelixSFD
FelixSFD

Reputation: 6092

Your code contains some more errors than you describe. I copied your code into a playground tried to fix it. I can't guarantee that it will work (I have never worked with HealthKit before, but it should at least compile.

Error 0*

In Swift 3, some classes have been renamed. For example NSCalendar to Calendar. The first two lines within your function have to be changed to this:

let calendar = Calendar.current
var interval = DateComponents()

Error 1

To get a date from date components, you have to use this function:

calendar.date(from: anchorComponents)

Error 2:

After reading the documentation about HKStatisticsCollectionQuery and HKQuantityType I came up with this line of code:

let stepsQuery = HKStatisticsCollectionQuery(quantityType: HKQuantityType.quantityType(forIdentifier: .activeEnergyBurned)!, quantitySamplePredicate: nil, options: .cumulativeSum, anchorDate: anchorDate!, intervalComponents: interval)

HKQuantityType.quantityType(forIdentifier: .activeEnergyBurned) replaces the HKQuantityType in your old code.

anchorDate: receives a Date instead of DateComponents.

And the enum-case you pass to options: starts with a lowercase letter in Swift 3.

Error 3*

dateByAddingUnit has been changed. In Swift 3, you use this:

calendar.date(byAdding: .day, value: -7, to: endDate)

(Again, the enum-case now starts with a lowercase letter.)

Error 4*

enumerateStatistics has been changed, too. It's now:

enumerateStatistics(from: startDate!, to: endDate)

Error 5*

HKUnit.countUnit() has been renamed:

let steps = quantity.doubleValue(for: HKUnit.count())

Error 6*

The way to use multiple threads has been changed massively.

DispatchQueue.main.async {
    //update UI components
}

Error 7*

HKHealthStore?.executeQuery(stepsQuery) is a bit strange. execute(_:) (as it is named in Swift 3) is not static and can only be used on instances of HKHealthStore. I fixed the error-message with the following line, but I'm not sure, if this will really work.

HKHealthStore().execute(stepsQuery)

*Additional errors I have found in your code when using it in a Playground.

Upvotes: 8

Related Questions