有一个非常普通的地图视图,显示 iPhone 的当前位置。
当我升级到 Swift 5.8 时,开始收到一些紫色警告。阅读本文后,这些将是 Xcode 处理数据方式的错误或变化。我正在使用 Xcode 15/beta 5。
错误出现在线路上:
class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
}
和
if CLLocationManager.locationServicesEnabled() {
以下分别是错误消息:
-locationManagerDidChangeAuthorization:
回调和检查
首先authorizationStatus
。完整代码如下:
import SwiftUI
import MapKit
class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
}
struct LocationView: View {
@Binding var selectedTab: TabChoice
@Binding var calculated: CalculatedChoice
@StateObject private var viewModel = LocationViewModel()
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: GlobalVariables.latitude, longitude: GlobalVariables.longitude), span: MKCoordinateSpan(latitudeDelta: GlobalVariables.zoomLevel, longitudeDelta: GlobalVariables.zoomLevel))
var body: some View {
NavigationView {
let displayTextLeft: String = "Latitude: " + String(format: "%.3f°", (viewModel.region.center.latitude))
let displayTextRight: String = "Longitude: " + String(format: "%.3f°", (viewModel.region.center.longitude))
// "Altitude: " + String(format: "%.0fm", (LocationManager.location?.altitude))
VStack {
ZStack(alignment: .top) {
VStack{
Text("Location")
.viewTitle()
// MARK: MAP API
VStack(alignment: .leading, spacing: 12) {
Map(coordinateRegion: $viewModel.region, showsUserLocation: true)
// .ignoresSafeArea()
.accentColor(Color(.systemPink))
.onAppear {
viewModel.checkIfLocationServicesIsEnabled()
}
}
.frame(width: GlobalVariables.screenWidth - 32, height: 340 + 30) // 30 = top + bottom padding from CalculateView
.clipShape(RoundedRectangle(cornerRadius: 15))
.overlay(
RoundedRectangle(cornerRadius: 15)
.stroke(.black, lineWidth: 2)
)
.padding(.leading, 16)
.padding(.trailing, 16)
.offset(y: -30)
// MARK: GREY BANNER
HStack {
Rectangle().fill(Color.gray)
.frame(width: GlobalVariables.screenWidthPadding, height: 24)
.overlay(
Text(displayTextLeft + " " + displayTextRight)
.greyBannerText()
)
}
.greyBannerPaddingRadius()
.offset(y: -24)
// MARK: TEXT
.frame(width: GlobalVariables.screenWidth, height: 24, alignment: .center)
VStack {
Text("How much solar power you can generate depends on where in the world you live. Not just how near the equator you are but the average amount of sunlight, cloud cover etc. Once your current location is showing correctly press the blue button below.")
.explanationTextPadding()
}
.offset(y: -24)
Spacer()
VStack {
// MARK: BUTTON
Button(action:
{ saveCoorindates()
selectedTab = TabChoice.calculate
}
, label: { Text("Press to Save Current Location")
.blueButtonTextFrame()
})
.blueButtonTextAttributes()
Spacer()
.frame(height: 20)
}
}
}
.onAppear {
}
} // NavigationStack
.toolbar(.hidden)
.navigationBarBackButtonHidden(true)
.navigationViewStyle(.stack)
} // VStack
}
}
func saveCoorindates() {
GlobalVariables.latitude = (CLLocationManager().location?.coordinate.latitude)!
GlobalVariables.longitude = (CLLocationManager().location?.coordinate.longitude)!
// GlobalVariables.altitude = (CLLocationManager().location?.coordinate.altitude)!
}
// MARK: CLLOCATION MANAGER
final class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
var locationManager: CLLocationManager?
@Published var region = MKCoordinateRegion(center: MapDetails.startingLocation, span: MapDetails.defaultSpan)
func checkIfLocationServicesIsEnabled () {
// DispatchQueue.global().async {
if CLLocationManager.locationServicesEnabled() {
self.locationManager = CLLocationManager()
self.locationManager!.delegate = self
self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
} else {
print("Location services are not enabled, please turn on.")
}
// }
}
private func checkLocationAuthorization() {
guard let locationManager = locationManager else { return }
switch locationManager.authorizationStatus {
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .restricted:
print("Your location is restricted due to parental controls.")
case .denied:
print("You have denied this app location permission. Go into settings to change it.")
case .authorizedAlways, .authorizedWhenInUse :
region = MKCoordinateRegion(center: locationManager.location!.coordinate, span: MKCoordinateSpan(latitudeDelta: GlobalVariables.zoomLevel, longitudeDelta: GlobalVariables.zoomLevel))
@unknown default:
break
}
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
checkLocationAuthorization()
}
}
如果我在 CLLocationManager.locationServicesEnabled() 周围放置一个 DispatchQueue,第二个紫色错误就会消失,但它不会获取我的位置并诉诸默认的经/纬度。
func checkIfLocationServicesIsEnabled () {
DispatchQueue.global().async {
if CLLocationManager.locationServicesEnabled() {
self.locationManager = CLLocationManager()
self.locationManager!.delegate = self
self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
} else {
print("Location services are not enabled, please turn on.")
}
}
}