Coding01

Coding 点滴

0%

学习 iOS Widgets 开发之每日步数小组件(一)

每日步数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class StepsInteractor {
let healthStore = HKHealthStore()
let stepCountType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
// Access Step Count
let healthKitTypes: Set = [ HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)! ]

func retrieveStepsWithAuth(completion: @escaping (Double) -> Void) {
// Check for Authorization
if (healthStore.authorizationStatus(for: stepCountType) != HKAuthorizationStatus.sharingAuthorized) {
healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (success, error) in
if (success) {
// Authorization Successful
self.getSteps { (result) in
completion(result)
}
} else {
completion(-1)
}
}
} else {
self.getSteps { (result) in
completion(result)
}
}
}

func getSteps(completion: @escaping (Double) -> Void) {
let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!

let now = Date()
let startOfDay = now - 2.days
var interval = DateComponents()
interval.day = 1

let query = HKStatisticsCollectionQuery(
quantityType: stepsQuantityType,
quantitySamplePredicate: nil,
options: [.cumulativeSum],
anchorDate: startOfDay,
intervalComponents: interval)

query.initialResultsHandler = { _, result, error in
var resultCount = 0.0
result!.enumerateStatistics(from: startOfDay, to: now) { statistics, _ in
if let sum = statistics.sumQuantity() {
// Get steps (they are of double type)
resultCount = sum.doubleValue(for: HKUnit.count())
} // end if
// Return
completion(resultCount)
}
}

query.statisticsUpdateHandler = {
query, statistics, statisticsCollection, error in
// If new statistics are available
if let sum = statistics?.sumQuantity() {
let resultCount = sum.doubleValue(for: HKUnit.count())
// Return
completion(resultCount)
} // end if
}

healthStore.execute(query)
}
}

对于授权过了,就直接调用获取步数,否则先授权,后获取数据。

391607784210_.pic

Widget 写法已经足够简单了,直接看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//
// HealthStepsWidget.swift
// Widget
//
// Created by 叶梅树 on 2020/12/12.
//

import WidgetKit
import SwiftUI
import Intents
import SwiftDate

struct HealthStepsProvider: IntentTimelineProvider {
let stepsInteractor = StepsInteractor()
func placeholder(in context: Context) -> HealthStepsEntry {
return HealthStepsEntry(date: Date(), steps: 0)
}

func getSnapshot(for configuration: HealthStepsIntent, in context: Context, completion: @escaping (HealthStepsEntry) -> Void) {
let entry = HealthStepsEntry(date: Date(), steps: 0)
completion(entry)
}

func getTimeline(for configuration: HealthStepsIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
let currentDate = Date()
let refreshDate = currentDate + 1.hours
stepsInteractor.retrieveStepsWithAuth { result in
let entry = HealthStepsEntry(date: Date(), steps: Int(result))
let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
completion(timeline)
}
}
}

struct HealthStepsEntry: TimelineEntry {
public let date: Date
public let steps: Int
}

struct HealthStepsPlaceholderView : View {
//这里是PlaceholderView - 提醒用户选择部件功能
var body: some View {
HealthStepsView(steps: 0)
}
}

struct HealthStepsEntryView : View {
//这里是Widget的类型判断
@Environment(\.widgetFamily) var family: WidgetFamily
var entry: HealthStepsProvider.Entry

@ViewBuilder
var body: some View {
HealthStepsView(steps: entry.steps)
}
}

struct HealthStepsWidget: Widget {
private let kind: String = "HealthSteps"
public var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: HealthStepsIntent.self, provider: HealthStepsProvider()) { entry in
HealthStepsEntryView(entry: entry)
}
.configurationDisplayName("每日步数")
.description("今日步数达到目标了吗?")
.supportedFamilies([.systemSmall])

}
}

看看 View 视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import SwiftUI

struct HealthStepsView: View {
var steps: Int
var body: some View {
VStack(alignment: .leading, spacing: 0.0) {
Spacer()
Text(String(steps))
.font(.footnote)
.foregroundColor(.gray)
.lineLimit(1)
Spacer()
}.padding(.all)
}
}

显示很简单:

401607784228_.pic

总结

下一步就是模仿已有的竞品效果:

Welcome to my other publishing channels