为何指南针Tab未激活时仍振动?SwiftUI指南针开发问题
解决切换Tab后指南针后台振动的问题
方案一:仅控制振动触发时机
通过跟踪视图的活跃状态,只在视图可见时触发振动:
import SwiftUI import CoreLocation struct CompassView : View { @ObservedObject var compassHeading = CompassHeading() @State private var isViewActive = false // 提前初始化反馈生成器,避免重复创建 private let feedbackGenerator = UIImpactFeedbackGenerator(style: .soft) var body: some View { ZStack { /* compass shapes and formatting */ } .onAppear { isViewActive = true // 提前准备反馈生成器,提升响应速度 feedbackGenerator.prepare() } .onDisappear { isViewActive = false } .onChange(of: compassHeading.degrees) { _ in guard isViewActive else { return } feedbackGenerator.impactOccurred() // 振动后重新准备,确保下次振动正常 feedbackGenerator.prepare() } } }
方案二:暂停指南针的后台更新(更优)
从根源上停止视图不可见时的角度更新,既避免振动,又节省系统资源:
首先给CompassHeading类添加启动/停止更新的方法(基于CLLocationManager实现):
class CompassHeading: ObservableObject { @Published var degrees: Double = 0.0 private let locationManager = CLLocationManager() init() { locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest } // 启动方位更新 func startUpdating() { locationManager.startUpdatingHeading() } // 停止方位更新 func stopUpdating() { locationManager.stopUpdatingHeading() } } extension CompassHeading: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) { degrees = newHeading.trueHeading } }
然后在CompassView中调用这些方法:
struct CompassView : View { @ObservedObject var compassHeading = CompassHeading() private let feedbackGenerator = UIImpactFeedbackGenerator(style: .soft) var body: some View { ZStack { /* compass shapes and formatting */ } .onAppear { compassHeading.startUpdating() feedbackGenerator.prepare() } .onDisappear { compassHeading.stopUpdating() } .onChange(of: compassHeading.degrees) { _ in feedbackGenerator.impactOccurred() feedbackGenerator.prepare() } } }
关键说明
- 方案一适合不想修改
CompassHeading的场景,仅做振动触发控制; - 方案二更高效,视图不可见时完全停止方位更新,减少系统资源消耗;
- 提前调用
feedbackGenerator.prepare()可避免振动响应延迟,提升体验。
内容的提问来源于stack exchange,提问作者Zack A
相关产品推荐
相关产品推荐

