skip to Main Content

I’m creating an app that contains a compass tab. I would like for it to vibrate upon changing degrees of orientation. I got it to work, however, when I switch over to a new tab I can still feel the compass vibrating in the background.

import SwiftUI
import CoreLocation

struct CompassView : View {
    @ObservedObject var compassHeading = CompassHeading()

    var body: some View {
        ZStack {
            /* compass shapes and formatting */
        }
        .onChange(of: compassHeading.degrees) {
            let generator = UIImpactFeedbackGenerator(style: .soft)
            generator.impactOccurred()
        }
    }
}

2

Answers


  1. .onChange(of: compassHeading.degrees) is likely to generate a LOT of changes.

    You’re probably feeling all the haptics that you queued up still playing long after you view has gone.

    Try debouncing your input via minimum change or limiting the number of haptic events that you can form. The first task will be to see how many events you’re creating with a print.

    Login or Signup to reply.
  2. CompassHeading Class:

    • Manages the compass updates using CLLocationManager.
    • Provides methods to start and stop updating the compass heading.

    CompassView:

    • Uses onAppear and onDisappear to manage the lifecycle of compass updates.
    • Incorporates a debounce mechanism to limit the frequency of haptic feedbacks. This prevents overloading the system with too many events.

    By adding the debounce mechanism to limit the number of haptic
    feedback events and managing the lifecycle of compass updates, we can
    ensure that the vibrations are more controlled and do not continue
    when switching tabs.

    class CompassHeading: NSObject, ObservableObject, CLLocationManagerDelegate {
        private var locationManager: CLLocationManager?
        @Published var degrees: Double = 0.0
        
        override init() {
            super.init()
            self.locationManager = CLLocationManager()
            self.locationManager?.delegate = self
        }
        
        func startUpdating() {
            self.locationManager?.startUpdatingHeading()
        }
    
        func stopUpdating() {
            self.locationManager?.stopUpdatingHeading()
        }
        
        func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
            degrees = newHeading.magneticHeading
        }
    }
    
    
    struct CompassView: View {
        @ObservedObject var compassHeading = CompassHeading()
        @State private var cancellable: AnyCancellable? = nil
    
        var body: some View {
           ZStack {
            }
    .onAppear {
                compassHeading.startUpdating()
                cancellable = compassHeading.$degrees
                    .debounce(for: .milliseconds(500), scheduler: RunLoop.main)
                    .sink { _ in
                        let generator = UIImpactFeedbackGenerator(style: .soft)
                        generator.impactOccurred()
                    }
            }
            .onDisappear {
                compassHeading.stopUpdating()
                cancellable?.cancel()
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search