通过Mac Catalyst运行iOS App时如何获取Mac摄像头完整宽幅画面
问题根源:Mac Catalyst默认运行在iOS兼容模式下,AVCaptureSession会强制将摄像头输出裁剪为iOS设备常用的宽高比,不会主动调用Mac摄像头的原生宽幅分辨率,不需要完全重构为原生Mac应用即可解决。
可行解决方案
1. 手动枚举获取内置广角摄像头
不要使用AVCaptureDevice.default(for: .video)获取设备,该接口在Catalyst环境下会返回适配iOS兼容模式的裁剪后实例,改为手动枚举指定广角摄像头:
// 替换原init中的设备获取逻辑 let deviceDiscovery = AVCaptureDevice.DiscoverySession( deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .unspecified ) guard let device = deviceDiscovery.devices.first else { fatalError("Could not find wide angle camera") }
2. 配置会话优先使用原生输入格式
关闭默认的会话预设裁剪,手动选择摄像头的原生宽幅格式:
session.beginConfiguration() // 关键配置:优先使用设备原生输入,不做上层裁剪 session.sessionPreset = .inputPriority // 手动选择设备最高分辨率的原生宽幅格式 if let wideFormat = device.formats.last(where: { format in format.mediaType == .video && CMFormatDescriptionGetDimensions(format.formatDescription).width > 1920 }) { do { try device.lockForConfiguration() device.activeFormat = wideFormat device.unlockForConfiguration() } catch { print("Set active format failed: \(error.localizedDescription)") } } // 确认可添加输入后再添加 guard session.canAddInput(input) else { fatalError("Could not add camera input") } session.addInput(input) session.commitConfiguration() session.startRunning()
3. 修改预览层显示规则避免裁剪
默认预览层的videoGravity为.resizeAspectFill,会自动裁切超出视图的画面,修改为.resizeAspect即可完整显示全部宽幅内容:
let preview = AVCaptureVideoPreviewLayer(session: session) preview.removeFromSuperlayer() preview.frame = self.view.bounds // 关键配置:按比例完整显示全部画面,不裁切 preview.videoGravity = .resizeAspect self.view.layer.insertSublayer(preview, at: 0)
4. 校验项目配置
- 打开项目目标的「Signing & Capabilities」,确认已添加Hardware > Camera权限
- 进入「Build Settings」,搜索
Mac Catalyst Interface Idiom,设置为Mac(不要选择iPad模式,该模式会强制按iOS适配规则裁剪摄像头输出)
内容的提问来源于stack exchange,提问作者Jon Vogel
相关产品推荐
相关产品推荐

