我将此示例代码用于我的应用程序,但是当我关闭摄像机视图控制器并且在动画完成之前很快出现问题时,我再次单击返回摄像机视图控制器的按钮。
崩溃说: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]
- &GT; 0x83897a&lt; + 28&gt;:陷阱
当我试图追踪问题时,它有时会引导我走向以下几行:
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
}
}
}