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

Completion Handler重复执行问题:SwiftLocation获取用户位置回调两次

Why Your Location Completion Block Runs Twice

Hey there! Let's break down why your completion block and print statements are firing twice—this is a common gotcha with continuous location updates in SwiftLocation.

The Root Cause

Looking at your LocationService.getUserLocation implementation, you're using frequency:.continuous when calling Location.getLocation().

In SwiftLocation, the .continuous frequency mode doesn't just return a single location fix—it keeps monitoring for location updates and triggers the success callback every time a new (or improved) location is detected. That's why you're seeing your completion block and print statements run multiple times (in your case, twice) as the location service gets a more accurate fix after the initial one.

Fixes to Try

You have two main options depending on your use case:

1. Get a Single Location Fix (Most Likely What You Want)

If you only need to fetch the user's location once, switch the frequency to .oneShot. This tells SwiftLocation to stop monitoring after it gets the first valid location, so your completion will only run once:

struct LocationService {
    static func getUserLocation(completion: @escaping (CLLocation?) -> Void){
        print("Attempting to get user location")
        Location.getLocation(accuracy: .city, frequency: .oneShot, success: { (_, location) -> Void in
            completion(location)
        }) { (request, last, error) -> Void in
            request.cancel()
            print("Location monitoring failed due to an error \(error)")
            completion(nil)
        }
    }
}

2. Keep Continuous Updates but Filter Duplicates

If you actually need ongoing location updates but don't want to process every single one, add a flag to track whether you've already handled the first valid location. You can also cancel the request manually after getting the fix if you don't need further updates:

struct LocationService {
    static func getUserLocation(completion: @escaping (CLLocation?) -> Void){
        print("Attempting to get user location")
        var hasProcessedLocation = false
        
        Location.getLocation(accuracy: .city, frequency:.continuous , success: { (request, location) -> Void in
            guard !hasProcessedLocation else { return }
            
            hasProcessedLocation = true
            completion(location)
            // Optional: Stop monitoring after first fix
            request.cancel()
        }) { (request, last, error) -> Void in
            request.cancel()
            print("Location monitoring failed due to an error \(error)")
            completion(nil)
        }
    }
}

Quick Recap

The .continuous mode is designed for real-time tracking (like navigation apps). For a one-time location check, .oneShot is the right choice. If you need ongoing updates, add logic to filter out redundant callbacks based on your needs.

内容的提问来源于stack exchange,提问作者Ron Baker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:17:06