在我的指南针应用程序中,我显示了航向,但性能不高:当我快速转动设备时,不会显示所有度数。我搜索的性能与Apple的natif罗盘应用程序相同。例如,当角度通过359到0度时,向notif用户发出振动。但是有时振动不会出现。
我的LocationProvider类:
import SwiftUI
import CoreLocation
import Combine
public class LocationProvider: NSObject, CLLocationManagerDelegate, ObservableObject {
private let locationManager: CLLocationManager
public let heading = PassthroughSubject<CGFloat, Never>()
@Published var currentHeading: CGFloat {
willSet {
heading.send(newValue)
}
}
public override init() {
currentHeading = 0
locationManager = CLLocationManager()
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingHeading()
locationManager.requestWhenInUseAuthorization()
}
public func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
self.currentHeading = CGFloat(newHeading.trueHeading)
}
}
我的contentView:
import SwiftUI
import CoreLocation
struct ContentView: View {
@ObservedObject var location: LocationProvider = LocationProvider()
@State var angle: CGFloat = 0
var body: some View {
VStack {
Text(String(Double(-self.location.currentHeading + 360).stringWithoutZeroFraction) + "°")
.font(.system(size: 80))
}
.onReceive(self.location.heading) { heading in
compassTapticFeedback(-heading + 360)
}
}
}
public extension Double {
var stringWithoutZeroFraction: String {
return String(format: "%.0f", self)
}
}
// Taptic feednack
func tapticFeedback(_ type: String) {
switch type {
case "heavy":
let tapticFeedback = UIImpactFeedbackGenerator(style: .heavy)
tapticFeedback.prepare()
tapticFeedback.impactOccurred()
case "medium":
let tapticFeedback = UIImpactFeedbackGenerator(style: .medium)
tapticFeedback.prepare()
tapticFeedback.impactOccurred()
case "light":
let tapticFeedback = UIImpactFeedbackGenerator(style: .light)
tapticFeedback.prepare()
tapticFeedback.impactOccurred()
default:
let tapticFeedback = UIImpactFeedbackGenerator(style: .medium)
tapticFeedback.prepare()
tapticFeedback.impactOccurred()
}
}
func compassTapticFeedback(_ angle: CGFloat) {
switch Int(angle) {
case 0:
tapticFeedback("heavy")
case 30:
tapticFeedback("heavy")
case 60:
tapticFeedback("heavy")
case 90:
tapticFeedback("heavy")
case 120:
tapticFeedback("heavy")
case 250:
tapticFeedback("heavy")
case 180:
tapticFeedback("heavy")
case 210:
tapticFeedback("heavy")
case 240:
tapticFeedback("heavy")
case 270:
tapticFeedback("heavy")
case 300:
tapticFeedback("heavy")
case 330:
tapticFeedback("heavy")
default:
return
}
}
可能是因为我在角度上进行了大量计算以获得没有零分数的值?我不知道。即使我不确定是什么原因。
问题是您正在检查当前角度是否为30
的倍数。问题是如果旋转设备的速度过快,该数字将被跳过,因此无法检测到。
按照下面其他技巧]的第二点所示,简化了compassTapticFeedback(_:)
的版本后,我添加了更多代码以使该方法检测之间的跳过角:
enum TapticSync { static var lastAngle: CGFloat = 0 } func compassTapticFeedback(_ angle: CGFloat) { // If the angle is 30°, carry on. Otherwise do more checks if !Int(angle).isMultiple(of: 30) { // If there was an angle at a multiple of 30° skipped, carry on. Otherwise do not trigger haptic feedback. let minVal = min(angle, TapticSync.lastAngle) let maxVal = max(angle, TapticSync.lastAngle) let roundUpToNextMultiple = ceil(minVal / 30) * 30 guard maxVal > roundUpToNextMultiple else { return } } // If the checks were passed, trigger the haptic feedback and update the last angle tapticFeedback("heavy") TapticSync.lastAngle = angle }
更多提示
.prepare()
在您的情况下,tapticFeedback.prepare()
中没有意义。如.prepare()
的文档中所述:
调用prepare(),然后立即触发反馈(之间没有任何时间)不会改善延迟。
您应该改为:
考虑何时可以最好地准备发电机。在触发反馈的事件之前调用prepare()。系统需要时间来准备Taptic Engine,以将延迟降至最低。
请参阅documentation以获取完整信息。
在您的情况下,您不需要switch
即可检查每个30倍的角度。相反,将compassTapticFeedback(_:)
更改为如下所示:
func compassTapticFeedback(_ angle: CGFloat) { if Int(angle).isMultiple(of: 30) { tapticFeedback("heavy") } }
3:指南针方向相反
由于这些部分,以度为单位的方向反转(删除了不必要的self.
:]
-location.currentHeading + 360 compassTapticFeedback(-heading + 360)
相反,因此度数顺时针增加,请使用:
location.currentHeading
compassTapticFeedback(heading)