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

Swift自定义iPhone相机:最优相机选型、变焦及Tap to Focus实现

Swift自定义相机最佳实践与问题解答

适配所有iPhone机型的deviceTypes设置

要覆盖所有iPhone后置相机,deviceTypes应包含以下类型,同时将position设为.back(仅筛选后置相机):

let deviceTypes: [AVCaptureDevice.DeviceType] = [
    .builtInTripleCamera,
    .builtInDualCamera,
    .builtInDualWideCamera,
    .builtInWideAngleCamera,
    .builtInTelephotoCamera,
    .builtInUltraWideCamera
]
let discoverySession = AVCaptureDevice.DiscoverySession(
    deviceTypes: deviceTypes,
    mediaType: .video,
    position: .back
)

这套配置能自动适配从老款单广角机型到最新三摄、双摄机型,系统会返回当前设备可用的后置相机列表。

多合一相机VS手动切换相机

优先选择builtInTripleCamera、builtInDualCamera这类多合一相机设备:

  • 这类设备是苹果系统整合的,自动处理不同镜头间的变焦切换、画质同步、过渡动画,体验和原生相机完全对齐。
  • 手动切换单相机需要自行处理镜头间的参数同步(如对焦、曝光)、变焦平滑过渡,容易出现卡顿或画质断层,开发成本更高。
  • 仅当设备无多合一相机时(比如老款单广角iPhone),才需要考虑手动切换单相机。

手动切换相机的最佳方案(仅无多合一相机时使用)

  1. 枚举并分组可用相机:先获取所有可用后置相机,按它们的变焦范围(minAvailableVideoZoomFactor和maxAvailableVideoZoomFactor)分组,比如超广角(0.5x)、广角(1x)、长焦(2x/3x)。
  2. 监听变焦变化:实时监听用户的变焦操作(如滑块拖动),当当前变焦系数超出当前相机的最大变焦范围时,切换到对应变焦区间的相机。
  3. 平滑切换会话:切换相机时,先暂停会话预览,替换AVCaptureDeviceInput后再重启会话,同时保留当前对焦、曝光参数,避免画面突兀变化。
  4. 处理变焦系数映射:切换相机后,将当前变焦系数转换为新相机的对应值(比如从广角切换到长焦,1x对应长焦的2x)。

TripleCamera下Tap to Focus失效的修复方案

你的代码存在两个核心问题:坐标未转换和支持性检查不完整,修复后的实现如下:

关键修复点

  1. 屏幕坐标转相机坐标系:屏幕Y轴方向和相机设备Y轴方向相反,需将点击点通过预览层转换为相机设备的归一化坐标(0~1范围)。
  2. 完善支持性检查:除对焦模式外,还要检查相机是否支持对焦兴趣点设置。
  3. 适配多合一相机的对焦逻辑:多合一相机建议使用.continuousAutoFocus模式(和原生相机一致),确保对焦持续稳定。

修复后的代码

func setFocusOnTap(screenPoint: CGPoint, previewView: UIView) {
    guard let cameraDevice = self.deviceInput?.device else { return }
    guard let previewLayer = previewView.layer as? AVCaptureVideoPreviewLayer else { return }
    
    // 转换屏幕点击点为相机设备的归一化坐标
    let cameraPoint = previewLayer.captureDevicePointConverted(fromLayerPoint: screenPoint)
    
    do {
        try cameraDevice.lockForConfiguration()
        
        // 对焦设置:检查兴趣点和模式支持
        if cameraDevice.isFocusPointOfInterestSupported, cameraDevice.isFocusModeSupported(.continuousAutoFocus) {
            cameraDevice.focusPointOfInterest = cameraPoint
            cameraDevice.focusMode = .continuousAutoFocus
        }
        
        // 曝光设置:同样检查兴趣点和模式支持
        if cameraDevice.isExposurePointOfInterestSupported, cameraDevice.isExposureModeSupported(.continuousAutoExposure) {
            cameraDevice.exposurePointOfInterest = cameraPoint
            cameraDevice.exposureMode = .continuousAutoExposure
        }
        
        cameraDevice.isSubjectAreaChangeMonitoringEnabled = true
        cameraDevice.unlockForConfiguration()
    } catch {
        print("Failed to configure focus: \(error)")
    }
}

额外注意事项

  • 确保调用该方法时在主线程:AVCaptureDevice的配置操作必须在主线程执行,否则可能出现异常。
  • 预览层的videoGravity设为.resizeAspectFill(和原生相机一致),避免坐标转换偏差。

整体最佳实践总结

  1. 优先选用多合一相机设备,减少手动管理成本,保证体验一致性。
  2. 动态检测可用相机,不要硬编码特定机型,确保适配所有iPhone。
  3. 所有相机配置操作必须在主线程执行。
  4. 涉及坐标转换时,务必使用AVCaptureVideoPreviewLayer的转换方法,避免手动计算出错。

内容的提问来源于stack exchange,提问作者Jesper Samuelsson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 16:50:20