da1lbi3 da1lbi3 - 1 year ago 397
Swift Question

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)")

} //end block
} //end if let



Answer Source

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.


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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download