更新到 Xcode 9 / Swift 4 后 AVCapture 出现奇怪的编译错误 [重复]

Posted

技术标签:

【中文标题】更新到 Xcode 9 / Swift 4 后 AVCapture 出现奇怪的编译错误 [重复]【英文标题】:Weird compile error with AVCapture after updating to Xcode 9 / Swift 4 [duplicate] 【发布时间】:2017-09-14 19:53:46 【问题描述】:

我有一个普通的UIViewController,它使用AVCapturePhoto,我在其中创建了一个自定义捕获控制器。

在我更新到 Xcode 9 并将我的代码转换为 Swift 4 之前一切正常,现在当我尝试编译时,我得到了这个编译错误:

架构 x86_64 的未定义符号: “__T0So22AVCapturePhotoSettingsC12AVFoundation01_abC16SwiftNativeTypesACWP”,引用自: __T05Union16CameraControllerC18handleCapturePhotoyyF 在 CameraController.o “__T012AVFoundation39_AVCapturePhotoSettingsSwiftNativeTypesPAAE016availablePreviewc11PixelFormatG0Says6UInt32VGfg”,引用自: __T05Union16CameraControllerC18handleCapturePhotoyyF 在 CameraController.o ld:未找到架构 x86_64 的符号 clang:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用)

并且在错误托盘中显示此消息:

Apple Mach-O 链接器错误组

任何提示可能是什么原因造成的?

更新信息

这是错误日志的 Xcode 9 打印屏幕。希望对编译错误解决方案有所帮助。

编辑

只是执行一些测试——如果我注释类代码,编译错误就会消失。

我在Swift 4 中缺少的以下class 实现有什么问题吗??

import UIKit
import AVFoundation


class CameraController: UIViewController, AVCapturePhotoCaptureDelegate, UIViewControllerTransitioningDelegate 

    let dismissButton: UIButton = 
        let button = UIButton(type: .system)
        button.setImage(#imageLiteral(resourceName: "right_arrow_shadow").withRenderingMode(.alwaysOriginal), for: .normal)
        button.addTarget(self, action: #selector(handleDismiss), for: .touchUpInside)
        return button
    ()

    let capturePhotoButton: UIButton = 
        let button = UIButton(type: .system)
        button.setImage(#imageLiteral(resourceName: "capture_photo").withRenderingMode(.alwaysOriginal), for: .normal)
        button.addTarget(self, action: #selector(handleCapturePhoto), for: .touchUpInside)
        return button
    ()

    let output = AVCapturePhotoOutput()

    override func viewDidLoad() 
        super.viewDidLoad()

        transitioningDelegate = self
        setupCaptureSession()
        setupHUD()
    


    // hiddes the status bar
    override var prefersStatusBarHidden: Bool  return true 

    //MARK: General funcs
    fileprivate func setupCaptureSession() 
        let captureSession = AVCaptureSession()

        //1. setup inputs - camera
        let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
        do 
            let input = try AVCaptureDeviceInput(device: captureDevice!)
            if captureSession.canAddInput(input) 
                captureSession.addInput(input)
            
         catch let err 
            print("Could not setup camera input:", err)
        
        //2. setup outputs
        if captureSession.canAddOutput(output) 
            captureSession.addOutput(output)
        
        //3.setup output preview
        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)      
        previewLayer.frame = view.frame
        view.layer.addSublayer(previewLayer)

        // starts the inputs/outputs
        captureSession.startRunning()
    


    fileprivate func setupHUD() 
        // botão de captura
        view.addSubview(capturePhotoButton)
        capturePhotoButton.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: nil, paddingTop: 0, paddinfLeft: 0, paddingBottom: 24, paddingRight: 0, width: 80, height: 80)
        capturePhotoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        // dismiss button
        view.addSubview(dismissButton)
        dismissButton.anchor(top: view.topAnchor, left: nil, bottom: nil, right: view.rightAnchor, paddingTop: 12, paddinfLeft: 0, paddingBottom: 0, paddingRight: 12, width: 50, height: 50)
    


    @objc func handleCapturePhoto() 
        // processes the captured photo
        let settings = AVCapturePhotoSettings()
        guard let preview = settings.availablePreviewPhotoPixelFormatTypes.first else  return 
        settings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: preview]
        output.capturePhoto(with: settings, delegate: self)
    


    @objc func handleDismiss() 
        dismiss(animated: true, completion: nil)
    


    // Camera delegate
    func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) 
        // access the captured image
        let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer!, previewPhotoSampleBuffer: previewPhotoSampleBuffer!)
        let previewImage = UIImage(data: imageData!)

        // shows the image
        let containerView = PreviewPhotoContainerView()
        containerView.previewImageView.image = previewImage

        view.addSubview(containerView)
        containerView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddinfLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

       

【问题讨论】:

您的未定义符号将分解为protocol witness table for __ObjC.AVCapturePhotoSettings : AVFoundation._AVCapturePhotoSettingsSwiftNativeTypes in AVFoundation @KevinBallard 抱歉,但我对您的评论有点迷茫。你是说我需要遵守 AVCapturePhotoSettings 协议? 我很困惑为什么这是另一个问题的重复。在我的 iphone7 上测试时出现了这个错误。将其标记为重复的人喝醉了!我找到了几种不使用该代码来解决我的问题的方法,#if arch(x86_64) 一种方法是在苹果意外私有化的一些 AVFoundation 类之前添加 2 个_(下划线)。例如将settings.availablePreviewPhotoPixelFormatTypes.first else 更改为settings.__availablePreviewPhotoPixelFormatTypes.first else。来源:forums.developer.apple.com/thread/86810#259270 这个错误的正确重复是这个***.com/questions/45668293/… 【参考方案1】:

所以我设法解决了这个问题。

不知何故,使用 Xcode 9,您无法实现在 ios 模拟器上无法运行的“免费”代码。

错误 - 解决后 - 非常简单。

我不能在模拟器中使用相机,因为它不起作用。

我认为 Xcode 可以提供更多有用的错误信息。

为了解决这个问题,我必须在我的 CameraController class 中编辑我的 handleCapturePhoto() 函数。

我必须检查是否使用的架构不是 x86_64 (simulator) ,然后我可以呈现相机输出。

这是函数求解状态:

@objc func handleCapturePhoto() 
    // processes the captured photo
    let settings = AVCapturePhotoSettings()

    // doesn't show in the simulator
    #if (!arch(x86_64))
        guard let preview = settings.previewPhotoFormat?.first else  return 
        settings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: preview]
        output.capturePhoto(with: settings, delegate: self)
    #endif

希望这对将来的人有所帮助。

【讨论】:

这将让您构建和运行您的项目,但不是问题的真正解决方案。我尝试了这个并替换了我找到的其他解决方案,没有使用#if (!arch(x86_64)),但它的行为并不像预期的那样。但是,如果它对你有用,它就对你有用。请注意,此解决方案可能会解决该问题,但会替换为新问题 这很简单。如果设备是模拟器 - 不要打开相机。这只是为了测试,在发布版本中,如果我愿意,我可以删除#ifdef 正如我所提到的,我在我的 iphone 7 上尝试了这个解决方案,它确实消除了编译错误,但它的行为方式与预期不同。因此,只需确保您的所有功能都按预期工作。如果是这样,你很好。 这实际上是 xcode 9 中的一个已知错误,苹果官方的回应是通过在每个 API 前面加上双下划线 (__) 来使用这些 API 的 SwiftPrivate 版本。例如,将AVCaptureDevice.Format.supportedColorSpaces 更改为AVCaptureDevice.Format.__supportedColorSpaces @ChristopherLarsen 是的,我知道(现在);我希望他们会在下一次 Xcode 更新中修复它,因为它很烦人

以上是关于更新到 Xcode 9 / Swift 4 后 AVCapture 出现奇怪的编译错误 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 9:使用 Swift 3.1 编译的模块无法在 Swift 4.0 中导入

Xcode 9.3(Swift 4.1)中的 Codable '没有初始化器'

如何在 Xcode 9.3 中切换到 Swift 4.0?

Xcode 9 Swift 4 Playgrounds UIGestureRecognizer 不工作

无法在 Swift 4 上的 XCUITest 中设置设备方向

无法在 Alamofire 中禁用缓存(Xcode 9 - swift 4)