Образец кода AVCam для Apple дает сбой

Я использовал этот пример кода для своего приложения, но возникает проблема, когда я закрываю контроллер представления камеры и незадолго до завершения анимации я нажимаю кнопку, которая снова возвращается к контроллеру представления камеры.

авария говорит:

libswiftCore.dylib`_swift_abortRetainUnowned:
0x83895e <+0>:  movw   r0, #0xe7ae
0x838962 <+4>:  movt   r0, #0x3
0x838966 <+8>:  add    r0, pc
0x838968 <+10>: ldr    r0, [r0]
0x83896a <+12>: movw   r1, #0xc1ad
0x83896e <+16>: movt   r1, #0x1
0x838972 <+20>: add    r1, pc
0x838974 <+22>: movs   r2, #0x0
0x838976 <+24>: str    r2, [r0, #0xc]
0x838978 <+26>: str    r1, [r0, #0x8]

-> 0x83897a ‹+28>: ловушка

И когда я пытался отследить проблему, это приводило меня иногда к следующим строкам:

DispatchQueue.main.async { [unowned self] in
            self.recordButton.isEnabled = self.movieFileOutput != nil
        }
    }

а иногда и к следующему:

self.movieFileOutput = movieFileOutput

Есть идеи?

thread #7: tid = 0x3ec7a, 0x007a097a libswiftCore.dylib`_swift_abortRetainUnowned + 28, queue = 'session queue', stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)
* frame #0: 0x007a097a libswiftCore.dylib`_swift_abortRetainUnowned + 28
frame #1: 0x007ad1bc libswiftCore.dylib`swift_unknownUnownedLoadStrong + 50
frame #2: 0x000aca0c quichar`CameraViewController.(self=0x176e5e01) -> ()).(closure #2) + 1804 at CameraViewController.swift:229
frame #3: 0x000a9a18 quichar`thunk + 56 at CameraViewController.swift:0
frame #4: 0x00e47d56 libdispatch.dylib`_dispatch_call_block_and_release + 10
frame #5: 0x00e53e62 libdispatch.dylib`_dispatch_queue_serial_drain + 980
frame #6: 0x00e4b204 libdispatch.dylib`_dispatch_queue_invoke + 556
frame #7: 0x00e54390 libdispatch.dylib`_dispatch_queue_override_invoke + 410
frame #8: 0x00e55d9e libdispatch.dylib`_dispatch_root_queue_drain + 408
frame #9: 0x00e55ba6 libdispatch.dylib`_dispatch_worker_thread3 + 112
frame #10: 0x1c49b936 libsystem_pthread.dylib`_pthread_wqthread + 1168
frame #11: 0x1c49b490 libsystem_pthread.dylib`start_wqthread + 8

вся функция выглядит следующим образом:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    sessionQueue.async {
        switch self.setupResult {
            case .success:
                // Only setup observers and start the session running if setup succeeded.
                self.addObservers()
                self.session.startRunning()
                self.isSessionRunning = self.session.isRunning

            case .notAuthorized:
                DispatchQueue.main.async { [unowned self] in
                    let message = NSLocalizedString("AVCam doesn't have permission to use the camera, please change privacy settings", comment: "Alert message when the user has denied access to the camera")
                    let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
                    alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))
                    alertController.addAction(UIAlertAction(title: NSLocalizedString("Settings", comment: "Alert button to open Settings"), style: .`default`, handler: { action in
                        UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)!, options: [:], completionHandler: nil)
                    }))

                    self.present(alertController, animated: true, completion: nil)
                }

            case .configurationFailed:
                DispatchQueue.main.async { [unowned self] in
                    let message = NSLocalizedString("Unable to capture media", comment: "Alert message when something goes wrong during capture session configuration")
                    let alertController = UIAlertController(title: "AVCam", message: message, preferredStyle: .alert)
                    alertController.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Alert OK button"), style: .cancel, handler: nil))

                    self.present(alertController, animated: true, completion: nil)
                }
        }
    }


// Switch to Video
    sessionQueue.async { [unowned self] in
        let movieFileOutput = AVCaptureMovieFileOutput()

        if self.session.canAddOutput(movieFileOutput) {
            self.session.beginConfiguration()
            self.session.addOutput(movieFileOutput)
            self.session.sessionPreset = AVCaptureSessionPreset352x288
            if let connection = movieFileOutput.connection(withMediaType: AVMediaTypeVideo) {
                if connection.isVideoStabilizationSupported {
                    connection.preferredVideoStabilizationMode = .auto
                }

            }
            self.session.commitConfiguration()
            //the first place where the problem arise.

            self.movieFileOutput = movieFileOutput
            DispatchQueue.main.async { [unowned self] in
                self.recordButton.isEnabled = true
            }
        }
    }
//Switch Cameras
    recordButton.isEnabled = false

    sessionQueue.async { [unowned self] in
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
        //Do Nothing
        } else {
            return
        }

        let currentVideoDevice = self.videoDeviceInput.device
        let currentPosition = currentVideoDevice!.position

        let preferredPosition: AVCaptureDevicePosition
        let preferredDeviceType: AVCaptureDeviceType

        switch currentPosition {
        case .unspecified, .front:
            preferredPosition = .back
            preferredDeviceType = AVCaptureDeviceType.builtInDualCamera

        case .back:
            preferredPosition = .front
            preferredDeviceType = .builtInWideAngleCamera
        }

        let devices = self.videoDeviceDiscoverySession.devices!
        var newVideoDevice: AVCaptureDevice? = nil

        // First, look for a device with both the preferred position and device type. Otherwise, look for a device with only the preferred position.
        if let device = devices.filter({ $0.position == preferredPosition && $0.deviceType == preferredDeviceType }).first {
            newVideoDevice = device
        }
        else if let device = devices.filter({ $0.position == preferredPosition }).first {
            newVideoDevice = device
        }

        if let videoDevice = newVideoDevice {
            do {
                let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice)

                self.session.beginConfiguration()

                // Remove the existing device input first, since using the front and back camera simultaneously is not supported.
                self.session.removeInput(self.videoDeviceInput)

                if self.session.canAddInput(videoDeviceInput) {
                    NotificationCenter.default.removeObserver(self, name: Notification.Name("AVCaptureDeviceSubjectAreaDidChangeNotification"), object: currentVideoDevice!)

                    NotificationCenter.default.addObserver(self, selector: #selector(self.subjectAreaDidChange), name: Notification.Name("AVCaptureDeviceSubjectAreaDidChangeNotification"), object: videoDeviceInput.device)

                    self.session.addInput(videoDeviceInput)
                    self.videoDeviceInput = videoDeviceInput
                }
                else {
                    self.session.addInput(self.videoDeviceInput);
                }

                if let connection = self.movieFileOutput?.connection(withMediaType: AVMediaTypeVideo) {
                    if connection.isVideoStabilizationSupported {
                        connection.preferredVideoStabilizationMode = .auto
                    }

                }

                /*
                 Set Live Photo capture enabled if it is supported. When changing cameras, the
                 `isLivePhotoCaptureEnabled` property of the AVCapturePhotoOutput gets set to NO when
                 a video device is disconnected from the session. After the new video device is
                 added to the session, re-enable Live Photo capture on the AVCapturePhotoOutput if it is supported.
                 */
                self.photoOutput.isLivePhotoCaptureEnabled = self.photoOutput.isLivePhotoCaptureSupported;

                self.session.commitConfiguration()
            }
            catch {
                print("Error occured while creating video device input: \(error)")
            }
        }
        //second place that is stop on

        DispatchQueue.main.async { [unowned self] in
            self.recordButton.isEnabled = self.movieFileOutput != nil
        }
    }



}

person FamousMaxy    schedule 27.03.2017    source источник
comment
Можете ли вы опубликовать трассировку стека вместе с контекстом кода, который вы разместили?   -  person NobodyNada    schedule 28.03.2017
comment
Извините. но как это сделать? это как эта печать (Thread.callStackSymbols)   -  person FamousMaxy    schedule 28.03.2017
comment
Самый простой способ — запустить bt в отладчике после сбоя — это даст вам текстовую трассировку стека, которую вы можете скопировать и вставить сюда. И под контекстом кода, который вы разместили, я имею в виду некоторый код, окружающий это - может быть, всю функцию и другие важные части определения класса.   -  person NobodyNada    schedule 28.03.2017
comment
вы имеете в виду точки останова? Извините за недопонимание.   -  person FamousMaxy    schedule 28.03.2017
comment
При сбое приложения введите bt в консоли отладчика в правом нижнем углу и нажмите клавишу возврата.   -  person NobodyNada    schedule 28.03.2017
comment
размещен над трассировкой стека.   -  person FamousMaxy    schedule 28.03.2017
comment
Не могли бы вы опубликовать еще немного CameraViewController? По крайней мере, функции, содержащие строки, которые вы разместили.   -  person NobodyNada    schedule 28.03.2017
comment
Написал выше всю функцию   -  person FamousMaxy    schedule 28.03.2017
comment
Как определяется movieFileOutput и почему вы везде используете unowned self?   -  person NobodyNada    schedule 28.03.2017
comment
Это пример кода, загруженный с Apple.   -  person FamousMaxy    schedule 28.03.2017
comment
если вы знаете, как решить эту проблему, пожалуйста, скажите мне?   -  person FamousMaxy    schedule 28.03.2017
comment
Проблема заключается в [unowned self] - когда вы быстро закрываете контроллер представления, контроллер представления освобождается. См. stackoverflow.com/q/42542071/3476191.   -  person NobodyNada    schedule 28.03.2017
comment
Спасибо. но я просто удалил слова [непринадлежащее себе] во всех местах, которые вызывали проблему и решали мою проблему.   -  person FamousMaxy    schedule 28.03.2017