├── PagerManagerView.swift └── ContentView.swift /PagerManagerView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct PagerManager: View { 4 | let pageCount: Int 5 | @Binding var currentIndex: Int 6 | let content: Content 7 | 8 | //Set the initial values for the variables 9 | init(pageCount: Int, currentIndex: Binding, @ViewBuilder content: () -> Content) { 10 | self.pageCount = pageCount 11 | self._currentIndex = currentIndex 12 | self.content = content() 13 | } 14 | 15 | @GestureState private var translation: CGFloat = 0 16 | 17 | //Set the animation 18 | var body: some View { 19 | GeometryReader { geometry in 20 | HStack(spacing: 0) { 21 | self.content.frame(width: geometry.size.width) 22 | } 23 | .frame(width: geometry.size.width, alignment: .leading) 24 | .offset(x: -CGFloat(self.currentIndex) * geometry.size.width) 25 | .offset(x: self.translation) 26 | 27 | 28 | .gesture( 29 | DragGesture().updating(self.$translation) { value, state, _ in 30 | state = value.translation.width 31 | }.onEnded { value in 32 | let offset = value.translation.width / geometry.size.width 33 | let newIndex = (CGFloat(self.currentIndex) - offset).rounded() 34 | self.currentIndex = min(max(Int(newIndex), 0), self.pageCount - 1) 35 | } 36 | ) 37 | } 38 | } 39 | } 40 | 41 | struct ContentView: View { 42 | @State private var currentPage = 0 43 | 44 | var body: some View { 45 | 46 | //Pager Manager 47 | VStack{ 48 | PagerManager(pageCount: 2, currentIndex: $currentPage) { 49 | Text("First page") 50 | Text("Second page") 51 | } 52 | 53 | Spacer() 54 | 55 | //Page Control 56 | HStack{ 57 | Circle() 58 | .frame(width: 8, height: 8) 59 | .foregroundColor(currentPage==1 ? Color.gray:Color.white) 60 | Circle() 61 | .frame(width: 8, height: 8) 62 | .foregroundColor(currentPage==1 ? Color.white:Color.gray) 63 | } 64 | } 65 | } 66 | 67 | } 68 | 69 | struct ContentView_Previews: PreviewProvider { 70 | static var previews: some View { 71 | ContentView() 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ContentView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | import HealthKit 3 | 4 | struct ContentView: View { 5 | private var healthStore = HKHealthStore() 6 | let heartRateQuantity = HKUnit(from: "count/min") 7 | 8 | @State private var value = 0 9 | 10 | var body: some View { 11 | VStack{ 12 | HStack{ 13 | Text("❤️") 14 | .font(.system(size: 50)) 15 | Spacer() 16 | 17 | } 18 | 19 | HStack{ 20 | Text("\(value)") 21 | .fontWeight(.regular) 22 | .font(.system(size: 70)) 23 | 24 | Text("BPM") 25 | .font(.headline) 26 | .fontWeight(.bold) 27 | .foregroundColor(Color.red) 28 | .padding(.bottom, 28.0) 29 | 30 | Spacer() 31 | 32 | } 33 | 34 | } 35 | .padding() 36 | .onAppear(perform: start) 37 | } 38 | 39 | 40 | func start() { 41 | autorizeHealthKit() 42 | startHeartRateQuery(quantityTypeIdentifier: .heartRate) 43 | } 44 | 45 | func autorizeHealthKit() { 46 | let healthKitTypes: Set = [ 47 | HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!] 48 | 49 | healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { _, _ in } 50 | } 51 | 52 | private func startHeartRateQuery(quantityTypeIdentifier: HKQuantityTypeIdentifier) { 53 | 54 | // 1 55 | let devicePredicate = HKQuery.predicateForObjects(from: [HKDevice.local()]) 56 | // 2 57 | let updateHandler: (HKAnchoredObjectQuery, [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?, Error?) -> Void = { 58 | query, samples, deletedObjects, queryAnchor, error in 59 | 60 | // 3 61 | guard let samples = samples as? [HKQuantitySample] else { 62 | return 63 | } 64 | 65 | self.process(samples, type: quantityTypeIdentifier) 66 | 67 | } 68 | 69 | // 4 70 | let query = HKAnchoredObjectQuery(type: HKObjectType.quantityType(forIdentifier: quantityTypeIdentifier)!, predicate: devicePredicate, anchor: nil, limit: HKObjectQueryNoLimit, resultsHandler: updateHandler) 71 | 72 | query.updateHandler = updateHandler 73 | 74 | // 5 75 | 76 | healthStore.execute(query) 77 | } 78 | 79 | private func process(_ samples: [HKQuantitySample], type: HKQuantityTypeIdentifier) { 80 | var lastHeartRate = 0.0 81 | 82 | for sample in samples { 83 | if type == .heartRate { 84 | lastHeartRate = sample.quantity.doubleValue(for: heartRateQuantity) 85 | } 86 | 87 | self.value = Int(lastHeartRate) 88 | } 89 | } 90 | } 91 | 92 | struct ContentView_Previews: PreviewProvider { 93 | static var previews: some View { 94 | ContentView() 95 | } 96 | } 97 | --------------------------------------------------------------------------------