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

iOS:如何获取拍摄中/已拍摄照片经纬度(替代废弃Assets Library)

嘿,刚好碰到过类似的需求,我来给你梳理清楚!你说得没错,Assets Library早在iOS 9就被苹果废弃了,所以得针对不同系统版本用对应的框架,同时还要覆盖iOS 5+的兼容性。下面分两种场景给你写示例代码:

一、获取已拍摄照片的经纬度

根据系统版本不同,我们用两个不同的框架来实现:

1. iOS 9.0+ 使用 Photos 框架(推荐)

Photos框架是苹果现在主推的,API更简洁易用,直接通过PHAsset的location属性就能拿到照片的位置信息。

import Photos

// 第一步:请求照片访问权限
PHPhotoLibrary.requestAuthorization { status in
    guard status == .authorized else {
        print("得先授予照片访问权限才能获取位置信息哦")
        return
    }
    
    // 这里以获取最近拍摄的一张照片为例,你可以根据需求调整筛选逻辑
    let fetchOptions = PHFetchOptions()
    // 按拍摄时间倒序,取最新的一张
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    fetchOptions.fetchLimit = 1
    
    let photoFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
    if let targetAsset = photoFetchResult.firstObject {
        // 读取位置信息
        if let photoLocation = targetAsset.location {
            let lat = photoLocation.coordinate.latitude
            let lng = photoLocation.coordinate.longitude
            print("这张照片的经纬度:lat = \(lat), lng = \(lng)")
        } else {
            print("这张照片没有标记位置哦")
        }
    }
}

2. iOS 5.0 - iOS 8.x 使用 Assets Library 框架(兼容低版本)

虽然这个框架已经废弃,但为了支持iOS 5-8的设备,还是得用上它:

import AssetsLibrary

// 直接遍历相册,取最新的照片
ALAssetsLibrary().enumerateGroupsWithTypes(ALAssetsGroupSavedPhotos, usingBlock: { group, stop in
    guard let validGroup = group else {
        print("无法访问相册分组")
        return
    }
    
    validGroup.setAssetsFilter(ALAssetsFilter.allPhotos())
    // 倒序遍历,取最新的一张
    validGroup.enumerateAssetsWithOptions(.Reverse) { asset, _, stopPointer in
        guard let validAsset = asset else { return }
        
        if let assetLocation = validAsset.location {
            let lat = assetLocation.coordinate.latitude
            let lng = assetLocation.coordinate.longitude
            print("这张照片的经纬度:lat = \(lat), lng = \(lng)")
            stopPointer.memory = true // 找到后停止遍历,节省资源
        } else {
            print("这张照片没有位置标记")
            stopPointer.memory = true
        }
    }
}, failureBlock: { error in
    print("访问相册失败:\(error.localizedDescription)")
})
二、拍摄中获取经纬度(并写入照片元数据)

如果是你自己的相机功能,想要在拍摄时获取当前位置并写入照片,就得结合CoreLocation来获取实时位置,再根据系统版本保存带位置的照片:

import UIKit
import CoreLocation
import Photos // iOS9+ 用这个,低版本用AssetsLibrary

class CameraDemoVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, CLLocationManagerDelegate {
    
    private let locationManager = CLLocationManager()
    private var currentUserLocation: CLLocation?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 请求位置权限,拍摄时需要获取当前位置
        if CLLocationManager.authorizationStatus() != .authorizedWhenInUse {
            locationManager.requestWhenInUseAuthorization()
        }
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }
    
    // 打开系统相机的方法
    @IBAction func openSystemCamera(_ sender: UIButton) {
        guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
            print("当前设备不支持相机功能")
            return
        }
        let cameraPicker = UIImagePickerController()
        cameraPicker.sourceType = .camera
        cameraPicker.delegate = self
        present(cameraPicker, animated: true)
    }
    
    // CoreLocation获取位置更新的回调
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // 取最新的位置
        currentUserLocation = locations.last
        // 获取到位置后就停止更新,节省电量
        locationManager.stopUpdatingLocation()
    }
    
    // 拍摄完成的回调
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true)
        
        guard let capturedImage = info[.originalImage] as? UIImage else {
            print("无法获取拍摄的照片")
            return
        }
        
        if let userLocation = currentUserLocation {
            // 保存带位置信息的照片
            savePhotoWithLocation(image: capturedImage, location: userLocation)
        } else {
            // 没获取到位置,直接保存照片
            savePhoto(image: capturedImage)
        }
    }
    
    // 兼容版本的保存带位置照片的方法
    private func savePhotoWithLocation(image: UIImage, location: CLLocation) {
        if #available(iOS 9.0, *) {
            PHPhotoLibrary.shared().performChanges({
                let creationRequest = PHAssetCreationRequest.forAsset()
                guard let imageData = image.jpegData(compressionQuality: 0.8) else { return }
                creationRequest.addResource(with: .photo, data: imageData, options: nil)
                // 设置照片的位置元数据
                creationRequest.location = location
            }) { success, error in
                if success {
                    print("带位置的照片保存成功啦")
                } else {
                    print("保存失败:\(error?.localizedDescription ?? "未知错误")")
                }
            }
        } else {
            // iOS8及以下用AssetsLibrary处理
            let assetsLibrary = ALAssetsLibrary()
            guard let imageData = image.jpegData(compressionQuality: 0.8) else { return }
            
            assetsLibrary.writeImageDataToSavedPhotosAlbum(imageData, metadata: nil) { assetURL, error in
                if let error = error {
                    print("保存照片失败:\(error.localizedDescription)")
                    return
                }
                
                // 给已保存的照片添加位置信息
                assetsLibrary.asset(for: assetURL!) { asset in
                    asset?.setLocation(location) { error in
                        if error == nil {
                            print("带位置的照片保存成功啦")
                        } else {
                            print("添加位置信息失败:\(error?.localizedDescription ?? "未知错误")")
                        }
                    }
                } failureBlock: { error in
                    print("获取照片Asset失败:\(error?.localizedDescription ?? "未知错误")")
                }
            }
        }
    }
    
    // 兼容版本的普通保存照片方法
    private func savePhoto(image: UIImage) {
        if #available(iOS 9.0, *) {
            PHPhotoLibrary.shared().performChanges({
                guard let imageData = image.jpegData(compressionQuality: 0.8) else { return }
                PHAssetCreationRequest.forAsset().addResource(with: .photo, data: imageData, options: nil)
            }) { success, error in
                print(success ? "照片保存成功" : "保存失败:\(error?.localizedDescription ?? "未知错误")")
            }
        } else {
            ALAssetsLibrary().writeImageToSavedPhotosAlbum(image.cgImage!, orientation: ALAssetOrientation(rawValue: image.imageOrientation.rawValue)!) { _, error in
                print(error == nil ? "照片保存成功" : "保存失败:\(error?.localizedDescription ?? "未知错误")")
            }
        }
    }
}

重要注意事项

  1. 权限配置:一定要在Info.plist里添加对应的权限描述,不然App会崩溃:
    • 照片访问:NSPhotoLibraryUsageDescription(iOS10+)、NSPhotoLibraryAddUsageDescription(如果只需要添加照片到相册)
    • 位置访问:NSLocationWhenInUseUsageDescription(拍摄时获取位置需要)
  2. 版本判断:用#available做运行时判断,避免在高版本系统调用废弃API的警告。
  3. 资源优化:获取到位置后记得停止CoreLocation的更新,避免不必要的电量消耗。

内容的提问来源于stack exchange,提问作者Louis Ferraiolo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:31:04