首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS CLGeocoder 郵編/城市轉經緯度:地理編碼完整實現與錯誤處理

     編輯:程式設計綜合問答

核心 API:CLGeocoder

CLGeocoder 將地址字串 (郵編、城市、詳細地址) 轉換為 CLPlacemark (含經緯度、行政區劃等)。

基本用法


let geocoder = CLGeocoder()
let address = "10001" // 紐約郵編,或 "北京市朝陽區"

geocoder.geocodeAddressString(address) { placemarks, error in
    if let error = error {
        print("地理編碼失敗: \(error.localizedDescription)")
        // 錯誤碼處理: kCLErrorNetwork, kCLErrorGeocodeFoundNoResult 等
        return
    }
    
    guard let placemark = placemarks?.first else {
        print("無結果")
        return
    }
    
    if let location = placemark.location {
        let lat = location.coordinate.latitude
        let lon = location.coordinate.longitude
        print("座標: \(lat), \(lon)")
        // 使用座標...
    }
    
    // 額外信息
    print("國家: \(placemark.country ?? "")")
    print("城市: \(placemark.locality ?? "")")
    print("郵編: \(placemark.postalCode ?? "")")
}

進階:限制搜索區域 (提升精準度)


// 僅在指定區域內搜索 (如當前地圖可見區域)
let region = CLCircularRegion(center: mapView.region.center, 
                              radius: mapView.region.span.latitudeDelta * 111000, 
                              identifier: "map_region")
geocoder.geocodeAddressString(address, in: region) { placemarks, error in
    // 結果優先匹配區域內
}

反地理編碼:座標轉地址


let location = CLLocation(latitude: 39.9042, longitude: 116.4074)
geocoder.reverseGeocodeLocation(location) { placemarks, error in
    if let placemark = placemarks?.first {
        let address = [
            placemark.name,           // POI 名稱
            placemark.thoroughfare,   // 街道
            placemark.subThoroughfare,// 號碼
            placemark.locality,       // 城市
            placemark.administrativeArea, // 省/州
            placemark.postalCode,     // 郵編
            placemark.country         // 國家
        ].compactMap { $0 }.joined(separator: ", ")
        print("地址: \(address)")
    }
}

Objective-C 版本


CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:@"10001" 
             completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
    if (error) {
        NSLog(@"錯誤: %@", error.localizedDescription);
        return;
    }
    for (CLPlacemark *placemark in placemarks) {
        CLLocation *loc = placemark.location;
        NSLog(@"緯度: %f, 經度: %f", loc.coordinate.latitude, loc.coordinate.longitude);
    }
}];

錯誤處理與最佳實踐

錯誤碼含義處理建議
kCLErrorNetwork網絡不可用提示用戶檢查網絡、重試機制
kCLErrorGeocodeFoundNoResult無匹配結果提示「未找到地址」、建議輸入更詳細地址
kCLErrorGeocodeFoundPartialResult部分匹配返回結果但提示可能不準確
kCLErrorDeferred請求延遲 (頻率限制)指數退避重試、避免高頻調用

關鍵注意事項

  1. 網絡請求:必須在後台線程/異步執行,主線程調用會阻塞 UI
  2. 頻率限制:Apple 限制每分鐘請求次數,批量轉換需排隊延遲
  3. 語言環境:結果語言跟隨系統語言,可用 preferredLocale 指定
  4. 緩存策略:相同地址緩存結果,避免重複請求
  5. 權限:需 NSLocationWhenInUseUsageDescription (雖純地理編碼不強制,但建議配置)

現代 Swift 異步封裝


func geocodeAddress(_ address: String) async throws -> CLLocationCoordinate2D {
    let geocoder = CLGeocoder()
    let placemarks = try await geocoder.geocodeAddressString(address)
    guard let coordinate = placemarks.first?.location?.coordinate else {
        throw CLError(.geocodeFoundNoResult)
    }
    return coordinate
}

// 使用
Task {
    do {
        let coord = try await geocodeAddress("北京市海淀區")
        // 更新地圖...
    } catch {
        // 錯誤處理
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved