SwiftUI中如何使用CLLocationManager?(XCode14.3.1,iOS16.6)
在SwiftUI中使用CLLocationManager获取位置信息
一、解决协议一致性问题
你的编译器错误源于SMCLocation类未遵循CLLocationManagerDelegate协议。要让类遵循协议,需在类定义后添加协议名称;由于该协议基于Objective-C,类还需继承NSObject(Objective-C的根类)。
修正后的基础类结构如下:
import CoreLocation import Combine class SMCLocation: NSObject, ObservableObject, CLLocationManagerDelegate { // 用@Published标记属性,让SwiftUI视图能响应属性变化 @Published var longitude: Double = 0.0 @Published var latitude: Double = 0.0 @Published var valid: Bool = false private let locationManager = CLLocationManager() override init() { super.init() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest } // 请求位置权限并启动位置更新 func startUpdatingLocation() { locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() } // MARK: - CLLocationManagerDelegate // 处理位置更新回调 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last else { return } longitude = location.coordinate.longitude latitude = location.coordinate.latitude valid = true // 按需选择是否停止更新,比如仅获取一次位置时可启用 // locationManager.stopUpdatingLocation() } // 处理权限状态变化 func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { switch manager.authorizationStatus { case .notDetermined: manager.requestWhenInUseAuthorization() case .authorizedWhenInUse, .authorizedAlways: manager.startUpdatingLocation() case .denied, .restricted: valid = false @unknown default: valid = false } } }
关键改动说明:
- 让类继承
NSObject并遵循ObservableObject(SwiftUI响应式核心)、CLLocationManagerDelegate协议 - 用
@Published包装需要视图监听的属性,属性变化时自动触发视图刷新 - 实现
CLLocationManagerDelegate的核心方法,处理位置更新与权限状态变化 - 添加
startUpdatingLocation方法,触发权限请求与位置更新流程
二、完整SwiftUI「我的位置」示例应用
1. ContentView.swift
import SwiftUI struct ContentView: View { // 用@StateObject确保位置管理器实例与视图生命周期绑定 @StateObject private var locationManager = SMCLocation() var body: some View { VStack(spacing: 20) { Text("当前位置") .font(.title) if locationManager.valid { VStack(alignment: .leading, spacing: 10) { Text("经度: \(locationManager.longitude, specifier: "%.6f")") Text("纬度: \(locationManager.latitude, specifier: "%.6f")") } .font(.body) } else { Text("正在获取位置...") .foregroundColor(.gray) } Button("获取我的位置") { locationManager.startUpdatingLocation() } .buttonStyle(.borderedProminent) .padding() } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
2. 配置Info.plist权限
使用位置服务必须在Info.plist中添加权限描述:
- 添加
NSLocationWhenInUseUsageDescription,值为权限说明(比如"需要获取您的位置来计算太阳时间") - 若需后台位置访问,额外添加
NSLocationAlwaysAndWhenInUseUsageDescription
三、核心注意事项
- SwiftUI可与UIKit/CoreLocation完美兼容,无需担心混合开发问题
@StateObject用于在SwiftUI视图中创建ObservableObject实例,确保其生命周期与视图一致- 必须处理权限拒绝场景,避免应用异常
- 可根据需求调整
desiredAccuracy(位置精度)与更新频率
内容的提问来源于stack exchange,提问作者mikeolson
相关产品推荐
相关产品推荐

