You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xcode15中SwiftUI新Map API的UserAnnotation功能失效求助

解决MapKit SwiftUI中UserAnnotation获取位置失败(kCLErrorDomain Code=1)的问题

问题描述

参照WWDC2023《Meet MapKit for SwiftUI》教程,在Xcode15中使用_MapKit_SwiftUI框架的UserAnnotation()获取模拟器用户位置时功能失效,点击定位按钮后界面无限缓冲,报错:

CLLocationManager(<CLLocationManager: 0x600000010b20>) for <MKCoreLocationProvider: 0x600003000c60> did fail with error: Error Domain=kCLErrorDomain Code=1 "(null)"

已完成操作:

  • Info.plist中添加Privacy - Location Always Usage Description和Privacy - Location Always and When In Use Usage Description权限
  • 已设置模拟器位置

解决方案

1. 补充缺失的核心权限键

iOS 17+中,仅添加Always相关权限不足以支持前台位置请求,必须在Info.plist中补充**Privacy - Location When In Use Usage Description**键。requestWhenInUseAuthorization()依赖该描述,缺少会导致授权请求不触发,直接返回权限拒绝(对应Code=1错误)。

2. 修复CLLocationManager生命周期问题

当前代码在onAppear中创建的CLLocationManager是局部变量,会被立即销毁,无法正常处理权限请求和位置更新。需将其声明为视图的持久化属性:

@StateObject private var locationManager = CLLocationManager()

然后在onAppear中发起权限请求:

.onAppear {
    locationManager.requestWhenInUseAuthorization()
    // 若需后台位置权限,可在用户授权前台后再请求:
    // if locationManager.authorizationStatus == .authorizedWhenInUse {
    //     locationManager.requestAlwaysAuthorization()
    // }
}

3. 重置模拟器权限缓存

模拟器可能缓存旧的权限设置,导致新配置不生效:

  • 关闭模拟器
  • 执行终端命令:xcrun simctl erase all(会清除所有模拟器数据,注意备份)
  • 重新打开模拟器并运行App,重新授权位置权限

4. 优化权限请求逻辑

避免同时调用requestAlwaysAuthorization()和requestWhenInUseAuthorization(),这会导致权限请求冲突。根据App需求选择其一:

  • 仅前台使用位置:只调用requestWhenInUseAuthorization(),确保对应权限描述已添加
  • 需要后台位置:先请求前台权限,用户授权后再请求后台权限,且两个权限描述都要配置

代码修改示例(CustomMapViewLookAround.swift)

import SwiftUI
import _MapKit_SwiftUI

@available(iOS 17.0, *)
struct CustomMapViewLookAround: View {
    @State private var position: MapCameraPosition = .automatic
    @State private var visibleRegion: MKCoordinateRegion?
    @State  var route: MKRoute?
    @State var searchResults: [MKMapItem] = []
    @State private var selectedResult: MKMapItem?
    @StateObject private var locationManager = CLLocationManager() // 新增持久化管理对象
    
    func getDirections() {
        print("results count: \(searchResults.count)")
        route = nil
        guard let selectedResult else { return }
        let request = MKDirections.Request()
        request.source = MKMapItem(placemark: MKPlacemark(coordinate: .parking))
        request.destination = selectedResult
        Task {
            let directions = MKDirections(request: request)
            let response = try? await directions.calculate()
            route = response?.routes.first
        }
    }
    
    var body: some View {
        Map(position: $position, selection: $selectedResult) {
            Annotation("Parking", coordinate: .parking) {
                ZStack {
                    RoundedRectangle(cornerRadius: 5)
                        .fill(.background)
                    RoundedRectangle(cornerRadius: 5)
                        .stroke(.secondary, lineWidth: 5)
                    Image(systemName: "car")
                        .padding(5)
                }
            }
            .annotationTitles(.hidden)
            
            ForEach(searchResults, id: \.self) { result in
                Marker(item: result)
            }
            .annotationTitles(.hidden)
            
            if let route {
                MapPolyline(route)
                    .stroke(.blue, lineWidth: 5)
            }
            
            UserAnnotation()
            
        }
        .mapStyle(.standard)
        .safeAreaInset(edge: .bottom) {
            HStack {
                Spacer()
                VStack(spacing: 0) {
                    if let selectedResult {
                        ItemInfoView(route: route, selectedResult: selectedResult)
                            .frame(height: 128)
                            .clipShape(RoundedRectangle (cornerRadius: 10))
                            .padding([.top, .horizontal])
                    }
                    BeantownButtons(searchResults: $searchResults, position: $position, visibleRegion: visibleRegion)
                        .padding(.top)
                }
                Spacer()
            }
            .background(.thinMaterial)
        }
        .onChange(of: searchResults) {
            position = .automatic
        }
        .onMapCameraChange { context in
            visibleRegion = context.region
        }
        .onChange(of: selectedResult) {
            getDirections()
        }
        .mapControls {
            MapUserLocationButton()
            MapCompass()
            MapScaleView()
        }
        .onAppear {
            locationManager.requestWhenInUseAuthorization()
        }
    }
}

#Preview {
    if #available(iOS 17.0, *) {
        CustomMapViewLookAround()
    } else {
        EmptyView()
    }
}

内容的提问来源于stack exchange,提问作者S. S. Saruar Jahan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 08:27:33