diff --git a/ImagePicker.xcodeproj/project.pbxproj b/ImagePicker.xcodeproj/project.pbxproj index 75dd4d7..4a7cc77 100644 --- a/ImagePicker.xcodeproj/project.pbxproj +++ b/ImagePicker.xcodeproj/project.pbxproj @@ -567,6 +567,7 @@ SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -617,6 +618,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; VALIDATE_PRODUCT = YES; }; name = Release; @@ -674,7 +676,7 @@ SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -700,7 +702,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; diff --git a/ImagePicker.xcodeproj/project.xcworkspace/xcuserdata/newuser.xcuserdatad/UserInterfaceState.xcuserstate b/ImagePicker.xcodeproj/project.xcworkspace/xcuserdata/newuser.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..86727f2 Binary files /dev/null and b/ImagePicker.xcodeproj/project.xcworkspace/xcuserdata/newuser.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ImagePicker.xcodeproj/xcuserdata/newuser.xcuserdatad/xcschemes/xcschememanagement.plist b/ImagePicker.xcodeproj/xcuserdata/newuser.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..d7aaf9b --- /dev/null +++ b/ImagePicker.xcodeproj/xcuserdata/newuser.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,19 @@ + + + + + SchemeUserState + + ExampleApp.xcscheme + + orderHint + 1 + + ImagePicker.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/ImagePicker/AVPreviewView.swift b/ImagePicker/AVPreviewView.swift index 6055d4f..31bc7d6 100755 --- a/ImagePicker/AVPreviewView.swift +++ b/ImagePicker/AVPreviewView.swift @@ -65,9 +65,9 @@ final class AVPreviewView: UIView { // MARK: Private Methods private func applyVideoDisplayMode() { switch displayMode { - case .aspectFill: previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill - case .aspectFit: previewLayer.videoGravity = AVLayerVideoGravityResizeAspect - case .resize: previewLayer.videoGravity = AVLayerVideoGravityResize + case .aspectFill: previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill + case .aspectFit: previewLayer.videoGravity = AVLayerVideoGravity.resizeAspect + case .resize: previewLayer.videoGravity = AVLayerVideoGravity.resize } } } diff --git a/ImagePicker/AssetCell.swift b/ImagePicker/AssetCell.swift index af6bd76..af4e46f 100755 --- a/ImagePicker/AssetCell.swift +++ b/ImagePicker/AssetCell.swift @@ -47,7 +47,7 @@ class VideoAssetCell : AssetCell { iconView.contentMode = .center durationLabel.textColor = UIColor.white - durationLabel.font = UIFont.systemFont(ofSize: 12, weight: UIFontWeightSemibold) + durationLabel.font = UIFont.systemFont(ofSize: 12, weight: UIFont.Weight.semibold) durationLabel.textAlignment = .right contentView.addSubview(gradientView) diff --git a/ImagePicker/CaptureSession.swift b/ImagePicker/CaptureSession.swift index 6c04a45..fce3838 100755 --- a/ImagePicker/CaptureSession.swift +++ b/ImagePicker/CaptureSession.swift @@ -128,7 +128,7 @@ final class CaptureSession : NSObject { //note: when I added these 2 updates into a configuration block the lag was even worse sessionQueue.async { //when device is disconnected also video data output connection orientation is reset, so we need to set to new proper value - self.videoDataOutput?.connection(withMediaType: AVMediaTypeVideo)?.videoOrientation = new + self.videoDataOutput?.connection(with: AVMediaType.video)?.videoOrientation = new } } @@ -137,7 +137,7 @@ final class CaptureSession : NSObject { fileprivate let sessionQueue = DispatchQueue(label: "session queue", attributes: [], target: nil) fileprivate var setupResult: SessionSetupResult = .success fileprivate var videoDeviceInput: AVCaptureDeviceInput! - fileprivate lazy var videoDeviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera, AVCaptureDevice.DeviceType.builtInDuoCamera], mediaType: AVMediaTypeVideo, position: .unspecified) + fileprivate lazy var videoDeviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera, AVCaptureDevice.DeviceType.builtInDuoCamera], mediaType: AVMediaType.video, position: .unspecified) fileprivate var videoDataOutput: AVCaptureVideoDataOutput? fileprivate let videoOutpuSampleBufferDelegate = VideoOutputSampleBufferDelegate() @@ -185,8 +185,8 @@ final class CaptureSession : NSObject { access is optional. If audio access is denied, audio is not recorded during movie recording. */ - let mediaType = AVMediaTypeVideo - switch AVCaptureDevice.authorizationStatus(forMediaType: mediaType) { + let mediaType = AVMediaType.video + switch AVCaptureDevice.authorizationStatus(for: mediaType) { case .authorized: // The user has previously granted access to the camera. break @@ -201,7 +201,7 @@ final class CaptureSession : NSObject { create an AVCaptureDeviceInput for audio during session setup. */ sessionQueue.suspend() - AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { [capturedSelf = self] granted in + AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { [capturedSelf = self] granted in if granted { DispatchQueue.main.async { capturedSelf.delegate?.captureSession(capturedSelf, authorizationStatusGranted: .authorized) @@ -252,7 +252,7 @@ final class CaptureSession : NSObject { case .notAuthorized: log("capture session: not authorized") DispatchQueue.main.async { [weak self] in - let status = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video) self?.delegate?.captureSession(self!, authorizationStatusFailed: status) } @@ -309,9 +309,9 @@ final class CaptureSession : NSObject { switch presetConfiguration { case .livePhotos, .photos: - session.sessionPreset = AVCaptureSessionPresetPhoto + session.sessionPreset = AVCaptureSession.Preset.photo case .videos: - session.sessionPreset = AVCaptureSessionPresetHigh + session.sessionPreset = AVCaptureSession.Preset.high } // Add video input. @@ -319,14 +319,14 @@ final class CaptureSession : NSObject { var defaultVideoDevice: AVCaptureDevice? // Choose the back dual camera if available, otherwise default to a wide angle camera. - if let dualCameraDevice = AVCaptureDevice.defaultDevice(withDeviceType: AVCaptureDevice.DeviceType.builtInDuoCamera, mediaType: AVMediaTypeVideo, position: .back) { + if let dualCameraDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInDuoCamera, for: AVMediaType.video, position: .back) { defaultVideoDevice = dualCameraDevice } - else if let backCameraDevice = AVCaptureDevice.defaultDevice(withDeviceType: AVCaptureDevice.DeviceType.builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .back) { + else if let backCameraDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType.video, position: .back) { // If the back dual camera is not available, default to the back wide angle camera. defaultVideoDevice = backCameraDevice } - else if let frontCameraDevice = AVCaptureDevice.defaultDevice(withDeviceType: AVCaptureDevice.DeviceType.builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .front) { + else if let frontCameraDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType.video, position: .front) { // In some cases where users break their phones, the back wide angle camera is not available. In this case, we should default to the front wide angle camera. defaultVideoDevice = frontCameraDevice } @@ -405,7 +405,7 @@ final class CaptureSession : NSObject { // Add audio input, if fails no need to fail whole configuration do { - let audioDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio) + let audioDevice = AVCaptureDevice.default(for: AVMediaType.audio) let audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice!) if session.canAddInput(audioDeviceInput) { @@ -455,7 +455,7 @@ final class CaptureSession : NSObject { videoDataOutput!.alwaysDiscardsLateVideoFrames = true videoDataOutput!.setSampleBufferDelegate(videoOutpuSampleBufferDelegate, queue: videoOutpuSampleBufferDelegate.processQueue) - if let connection = videoDataOutput!.connection(withMediaType: AVMediaTypeVideo) { + if let connection = videoDataOutput!.connection(with: AVMediaType.video) { connection.videoOrientation = self.videoOrientation connection.automaticallyAdjustsVideoMirroring = false } @@ -604,17 +604,17 @@ extension CaptureSession { sessionQueue.async { [unowned self] in let currentVideoDevice = self.videoDeviceInput.device - let currentPosition = currentVideoDevice?.position + let currentPosition = currentVideoDevice.position let preferredPosition: AVCaptureDevice.Position let preferredDeviceType: AVCaptureDevice.DeviceType switch currentPosition { - case .unspecified?, .front?: + case .unspecified, .front: preferredPosition = .back preferredDeviceType = AVCaptureDevice.DeviceType.builtInDuoCamera - case .back?: + case .back: preferredPosition = .front preferredDeviceType = AVCaptureDevice.DeviceType.builtInWideAngleCamera default: @@ -622,14 +622,14 @@ extension CaptureSession { preferredDeviceType = AVCaptureDevice.DeviceType.builtInDuoCamera } - let devices = self.videoDeviceDiscoverySession?.devices + 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 { + if let device = devices.filter({ $0.position == preferredPosition && $0.deviceType == preferredDeviceType }).first { newVideoDevice = device } - else if let device = devices?.filter({ $0.position == preferredPosition }).first { + else if let device = devices.filter({ $0.position == preferredPosition }).first { newVideoDevice = device } @@ -653,7 +653,7 @@ extension CaptureSession { self.session.addInput(self.videoDeviceInput); } - if let connection = self.videoFileOutput?.connection(withMediaType: AVMediaTypeVideo) { + if let connection = self.videoFileOutput?.connection(with: AVMediaType.video) { if connection.isVideoStabilizationSupported { connection.preferredVideoStabilizationMode = .auto } @@ -670,7 +670,7 @@ extension CaptureSession { // when device is disconnected: // - video data output connection orientation is reset, so we need to set to new proper value // - video mirroring is set to true if camera is front, make sure we use no mirroring - if let videoDataOutputConnection = self.videoDataOutput?.connection(withMediaType: AVMediaTypeVideo) { + if let videoDataOutputConnection = self.videoDataOutput?.connection(with: AVMediaType.video) { videoDataOutputConnection.videoOrientation = self.videoOrientation if videoDataOutputConnection.isVideoMirroringSupported { videoDataOutputConnection.isVideoMirrored = true @@ -710,7 +710,7 @@ extension CaptureSession { sessionQueue.async { // Update the photo output's connection to match the video orientation of the video preview layer. - if let photoOutputConnection = self.photoOutput.connection(withMediaType: AVMediaTypeVideo) { + if let photoOutputConnection = self.photoOutput.connection(with: AVMediaType.video) { photoOutputConnection.videoOrientation = videoPreviewLayerOrientation } @@ -839,7 +839,7 @@ extension CaptureSession { } // update the orientation on the movie file output video connection before starting recording. - let movieFileOutputConnection = strongSelf.videoFileOutput?.connection(withMediaType: AVMediaTypeVideo) + let movieFileOutputConnection = strongSelf.videoFileOutput?.connection(with: AVMediaType.video) movieFileOutputConnection?.videoOrientation = videoPreviewLayerOrientation! // start recording to a temporary file. @@ -886,7 +886,7 @@ extension CaptureSession { recordingDelegate.savesVideoToLibrary = saveToPhotoLibrary // start recording - movieFileOutput.startRecording(toOutputFileURL: outputURL, recordingDelegate: recordingDelegate) + movieFileOutput.startRecording(to: outputURL, recordingDelegate: recordingDelegate) strongSelf.videoCaptureDelegate = recordingDelegate } } diff --git a/ImagePicker/CarvedLabel.swift b/ImagePicker/CarvedLabel.swift index 13b4385..2be0e9d 100755 --- a/ImagePicker/CarvedLabel.swift +++ b/ImagePicker/CarvedLabel.swift @@ -69,14 +69,14 @@ final class CarvedLabel : UIView { } fileprivate var textAttributes: TextAttributes { - let activeFont = font ?? UIFont.systemFont(ofSize: 12, weight: UIFontWeightRegular) + let activeFont = font ?? UIFont.systemFont(ofSize: 12, weight: UIFont.Weight.regular) return [ - NSFontAttributeName as NSString: activeFont + NSAttributedStringKey.font: activeFont ] } fileprivate var attributedString: NSAttributedString { - return NSAttributedString(string: text ?? "", attributes: textAttributes as [String : Any]) + return NSAttributedString(string: text ?? "", attributes: textAttributes) } override func draw(_ rect: CGRect) { diff --git a/ImagePicker/ImagePickerController.swift b/ImagePicker/ImagePickerController.swift index 2eb6481..58bf3ca 100755 --- a/ImagePicker/ImagePickerController.swift +++ b/ImagePicker/ImagePickerController.swift @@ -144,7 +144,7 @@ open class ImagePickerController : UIViewController { public var selectedAssets: [PHAsset] { get { let selectedIndexPaths = collectionView.indexPathsForSelectedItems ?? [] - let selectedAssets = selectedIndexPaths.flatMap { indexPath in + let selectedAssets = selectedIndexPaths.compactMap { indexPath in return asset(at: indexPath.row) } return selectedAssets @@ -514,7 +514,7 @@ extension ImagePickerController : ImagePickerDelegateDelegate { cell.updateRecordingVideoStatus(isRecording: isRecordingVideo, shouldAnimate: false) //update authorization status if it's changed - let status = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video) if cell.authorizationStatus != status { cell.authorizationStatus = status } diff --git a/ImagePicker/NoPermissionsView.swift b/ImagePicker/NoPermissionsView.swift index f055fcb..afd20fa 100644 --- a/ImagePicker/NoPermissionsView.swift +++ b/ImagePicker/NoPermissionsView.swift @@ -9,7 +9,7 @@ public class NoPermissionsView: UIView { label.translatesAutoresizingMaskIntoConstraints = false label.textAlignment = .center label.numberOfLines = 0 - label.font = .systemFont(ofSize: 17, weight: UIFontWeightRegular) + label.font = .systemFont(ofSize: 17, weight: UIFont.Weight.regular) let grayLevel: CGFloat = 153/255 label.textColor = UIColor(red: grayLevel, green: grayLevel, blue: grayLevel, alpha: 1.0) return label @@ -19,7 +19,7 @@ public class NoPermissionsView: UIView { let button = UIButton(type: .system) button.translatesAutoresizingMaskIntoConstraints = false button.setTitle(NSLocalizedString("Go to Settings", comment: ""), for: .normal) - button.titleLabel?.font = .systemFont(ofSize: 20, weight: UIFontWeightSemibold) + button.titleLabel?.font = .systemFont(ofSize: 20, weight: UIFont.Weight.semibold) return button }() @@ -41,7 +41,7 @@ public class NoPermissionsView: UIView { fatalError("init(coder:) has not been implemented") } - func navigateToSettings() { + @objc func navigateToSettings() { guard let settingsURL = URL(string: UIApplicationOpenSettingsURLString) else { return } UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil) } diff --git a/ImagePicker/PhotoCaptureDelegate.swift b/ImagePicker/PhotoCaptureDelegate.swift index 3f21b30..2d5918e 100755 --- a/ImagePicker/PhotoCaptureDelegate.swift +++ b/ImagePicker/PhotoCaptureDelegate.swift @@ -57,13 +57,13 @@ final class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate { completed(self) } - func capture(_ captureOutput: AVCapturePhotoOutput, willBeginCaptureForResolvedSettings resolvedSettings: AVCaptureResolvedPhotoSettings) { + func photoOutput(_ captureOutput: AVCapturePhotoOutput, willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings) { if resolvedSettings.livePhotoMovieDimensions.width > 0 && resolvedSettings.livePhotoMovieDimensions.height > 0 { capturingLivePhoto(true) } } - func capture(_ captureOutput: AVCapturePhotoOutput, willCapturePhotoForResolvedSettings resolvedSettings: AVCaptureResolvedPhotoSettings) { + func photoOutput(_ captureOutput: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) { willCapturePhotoAnimation() } @@ -81,7 +81,7 @@ final class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate { // } //this method is not called on iOS 11 if method above is implemented - func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) { + func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) { if let photoSampleBuffer = photoSampleBuffer { photoData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer) } @@ -92,11 +92,11 @@ final class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate { } } - func capture(_ captureOutput: AVCapturePhotoOutput, didFinishRecordingLivePhotoMovieForEventualFileAt outputFileURL: URL, resolvedSettings: AVCaptureResolvedPhotoSettings) { + func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishRecordingLivePhotoMovieForEventualFileAt outputFileURL: URL, resolvedSettings: AVCaptureResolvedPhotoSettings) { capturingLivePhoto(false) } - func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingLivePhotoToMovieFileAt outputFileURL: URL, duration: CMTime, photoDisplay photoDisplayTime: CMTime, resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) { + func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingLivePhotoToMovieFileAt outputFileURL: URL, duration: CMTime, photoDisplayTime: CMTime, resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) { if let error = error { log("photo capture delegate: error processing live photo companion movie: \(error)") return @@ -105,7 +105,7 @@ final class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate { livePhotoCompanionMovieURL = outputFileURL } - func capture(_ captureOutput: AVCapturePhotoOutput, didFinishCaptureForResolvedSettings resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) { + func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) { if let error = error { log("photo capture delegate: Error capturing photo: \(error)")