在 iOS 掃碼組件中實現自動對焦和曝光,核心依賴AVFoundation框架的AVCaptureDevice類,通過配置設備的對焦模式、曝光模式,結合用户交互(如點擊對焦)或環境檢測(如弱光自動補光)來實現智能調控。以下是分步實現方案,包含基礎自動對焦 / 曝光、手動觸發優化及特殊場景適配: 一、基礎配置:開啓自動對焦與曝光 首先需初始化AVCaptureSession並獲取攝像頭設備(通常為後置攝像頭),然後配置對焦和曝光的默認模式: swift import AVFoundation import UIKit

class ScanViewController: UIViewController { private let captureSession = AVCaptureSession() private var captureDevice: AVCaptureDevice? private let previewLayer = AVCaptureVideoPreviewLayer()

override func viewDidLoad() {
    super.viewDidLoad()
    setupCaptureSession()
}

// 初始化採集會話
private func setupCaptureSession() {
    // 1. 獲取後置攝像頭設備
    guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
        print("獲取攝像頭設備失敗")
        return
    }
    captureDevice = device
    
    // 2. 配置輸入(攝像頭)
    guard let input = try? AVCaptureDeviceInput(device: device) else {
        print("配置攝像頭輸入失敗")
        return
    }
    if captureSession.canAddInput(input) {
        captureSession.addInput(input)
    }
    
    // 3. 配置輸出(元數據,用於識別條碼)
    let metadataOutput = AVCaptureMetadataOutput()
    if captureSession.canAddOutput(metadataOutput) {
        captureSession.addOutput(metadataOutput)
        metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        metadataOutput.metadataObjectTypes = [.qr, .code128] // 指定識別碼制
    }
    
    // 4. 配置預覽層
    previewLayer.session = captureSession
    previewLayer.frame = view.bounds
    previewLayer.videoGravity = .resizeAspectFill
    view.layer.insertSublayer(previewLayer, at: 0)
    
    // 5. 開啓自動對焦和曝光
    setupAutoFocusAndExposure()
    
    // 啓動採集會話
    captureSession.startRunning()
}

// 配置自動對焦與曝光
private func setupAutoFocusAndExposure() {
    guard let device = captureDevice else { return }
    do {
        try device.lockForConfiguration() // 鎖定配置(必須)
        
        // 自動對焦:持續自動對焦(適合掃碼時隨條碼移動調整)
        if device.isFocusModeSupported(.continuousAutoFocus) {
            device.focusMode = .continuousAutoFocus
            device.focusPointOfInterest = CGPoint(x: 0.5, y: 0.5) // 對焦中心區域
        }
        
        // 自動曝光:持續自動曝光(根據環境光線調整)
        if device.isExposureModeSupported(.continuousAutoExposure) {
            device.exposureMode = .continuousAutoExposure
            device.exposurePointOfInterest = CGPoint(x: 0.5, y: 0.5) // 曝光中心區域
        }
        
        device.unlockForConfiguration() // 解鎖配置
    } catch {
        print("配置對焦/曝光失敗:\(error)")
    }
}

}

// 實現元數據代理(掃碼識別邏輯) extension ScanViewController: AVCaptureMetadataOutputObjectsDelegate { func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { // 處理識別結果... } } 二、進階優化:點擊屏幕手動對焦 + 曝光 掃碼時用户可能需要對準特定區域(如遠距離條碼),添加點擊預覽層觸發對焦 / 曝光: swift // 在viewDidLoad中添加點擊手勢 override func viewDidLoad() { super.viewDidLoad() setupCaptureSession() let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:))) view.addGestureRecognizer(tapGesture) }

// 處理點擊對焦 @objc private func handleTap(_ gesture: UITapGestureRecognizer) { let point = gesture.location(in: view) // 將點擊座標轉換為攝像頭的興趣區域座標(攝像頭座標系:0~1,原點在左上角) let cameraPoint = previewLayer.captureDevicePointConverted(fromLayerPoint: point) focus(with: cameraPoint) }

// 手動對焦+曝光 private func focus(with point: CGPoint) { guard let device = captureDevice else { return } do { try device.lockForConfiguration()

// 1. 手動對焦到點擊位置
    if device.isFocusModeSupported(.autoFocus) {
        device.focusPointOfInterest = point
        device.focusMode = .autoFocus // 單次自動對焦(對焦後恢復持續自動對焦)
        // 對焦完成後恢復持續對焦(可選)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            if device.isFocusModeSupported(.continuousAutoFocus) {
                device.focusMode = .continuousAutoFocus
            }
        }
    }
    
    // 2. 手動曝光到點擊位置
    if device.isExposureModeSupported(.autoExpose) {
        device.exposurePointOfInterest = point
        device.exposureMode = .autoExpose // 單次自動曝光
        // 曝光完成後恢復持續曝光(可選)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            if device.isExposureModeSupported(.continuousAutoExposure) {
                device.exposureMode = .continuousAutoExposure
            }
        }
    }
    
    device.unlockForConfiguration()
} catch {
    print("手動對焦/曝光失敗:\(error)")
}

} 三、弱光場景:自定義曝光參數(ISO / 快門) 若環境光線過暗,可手動調整曝光參數(如提高 ISO、延長快門時間),實現弱光補光: swift // 弱光下增強曝光 private func enhanceLowLightExposure() { guard let device = captureDevice else { return } do { try device.lockForConfiguration()

// 檢查是否支持自定義曝光
    if device.isExposureModeSupported(.custom) {
        // 設置曝光時長(單位:秒,需在device.minExposureDuration和maxExposureDuration之間)
        let exposureDuration = CMTimeMakeWithSeconds(1/30, preferredTimescale: 1000000000) // 30fps
        // 設置ISO(需在device.minISO和maxISO之間)
        let iso = min(400, device.maxISO) // 提高ISO至400(避免噪點過多)
        
        device.setExposureModeCustom(duration: exposureDuration, iso: iso, completionHandler: nil)
    }
    
    device.unlockForConfiguration()
} catch {
    print("自定義曝光失敗:\(error)")
}

} 四、閃光燈聯動:弱光自動開啓閃光燈 結合環境光檢測,在弱光時自動打開閃光燈輔助照明: swift // 自動控制閃光燈 private func autoToggleTorch() { guard let device = captureDevice, device.hasTorch else { return } do { try device.lockForConfiguration()

// 模擬環境光檢測(實際可通過亮度傳感器獲取)
    let isLowLight = true // 弱光標記
    device.torchMode = isLowLight ? .on : .off
    // 設置閃光燈亮度(0~1)
    if device.isTorchModeSupported(.on) {
        try device.setTorchModeOn(level: 0.8)
    }
    
    device.unlockForConfiguration()
} catch {
    print("閃光燈控制失敗:\(error)")
}

} 五、關鍵注意事項 配置鎖定機制:所有對AVCaptureDevice的配置修改必須在lockForConfiguration()和unlockForConfiguration()之間進行,否則會崩潰。 設備能力檢查:不同設備支持的對焦 / 曝光模式不同(如部分舊機型不支持自定義曝光),需通過isFocusModeSupported()、isExposureModeSupported()判斷。 座標系轉換:點擊屏幕的座標是UIKit座標系(原點在左上角),需通過previewLayer.captureDevicePointConverted(fromLayerPoint:)轉換為攝像頭的興趣區域座標(0~1 範圍)。 性能平衡:持續自動對焦 / 曝光會增加 CPU 消耗,若需極致性能,可在識別到條碼後暫停自動調整。 總結 通過AVFoundation的AVCaptureDevice配置,可實現基礎自動對焦 / 曝光、點擊手動調控及弱光場景優化,結合閃光燈聯動能進一步提升掃碼成功率。實際開發中需根據業務場景(如支付掃碼、商品盤點)調整策略,例如支付場景優先保證識別速度,商品盤點場景支持連續對焦適配批量掃碼。