diff --git a/.swiftformat b/.swiftformat index 81e1a64..05d5edb 100644 --- a/.swiftformat +++ b/.swiftformat @@ -1,5 +1,5 @@ # SwiftFormat configuration for IONCameraLib -# Targets iOS 14+ / Swift 5.9+ +# Targets iOS 15+ / Swift 5.9+ --swiftversion 5.9 --minversion 0.54.0 diff --git a/IONCameraLib.podspec b/IONCameraLib.podspec index da01bd4..367b868 100644 --- a/IONCameraLib.podspec +++ b/IONCameraLib.podspec @@ -11,7 +11,7 @@ Pod::Spec.new do |spec| spec.license = { :type => package['license'], :file => "LICENSE" } spec.author = { package['author'] => package['email'] } - spec.ios.deployment_target = "14.0" + spec.ios.deployment_target = "15.0" spec.source = { :git => package['repository']['url'], :tag => "#{spec.version}" } spec.source_files = "Sources/IONCameraLib/**/*.swift" diff --git a/Package.swift b/Package.swift index 68c3954..31dfe0b 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ import PackageDescription let package = Package( name: "IONCameraLib", platforms: [ - .iOS(.v14), + .iOS(.v15), ], products: [ .library( diff --git a/README.md b/README.md index 108d7f8..3fa2a2d 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ The library includes a `PrivacyInfo.xcprivacy` file that documents the required ## Requirements -- iOS 14.0+ +- iOS 15.0+ - Xcode 15.0+ - Swift 5.0+ diff --git a/Sources/IONCameraLib/Interfaces/IONCAMRMediaResultGenerator.swift b/Sources/IONCameraLib/Interfaces/IONCAMRMediaResultGenerator.swift index dae6f33..1f23054 100644 --- a/Sources/IONCameraLib/Interfaces/IONCAMRMediaResultGenerator.swift +++ b/Sources/IONCameraLib/Interfaces/IONCAMRMediaResultGenerator.swift @@ -8,26 +8,15 @@ private enum IONCAMRMetadataError: Error { final class IONCAMRMediaResultGenerator: IONCAMRMetadataGetterDelegate { func getVideoMetadata(from url: URL) async throws -> IONCAMRMetadata { - let asset = AVAsset(url: url) + let asset = AVURLAsset(url: url) - let durationProperty: CMTime - let trackArray: [AVAssetTrack] - if #available(iOS 15, *) { - durationProperty = try await asset.load(.duration) - trackArray = try await asset.loadTracks(withMediaType: .video) - } else { - durationProperty = asset.duration - trackArray = asset.tracks(withMediaType: .video) - } + let durationProperty = try await asset.load(.duration) + let trackArray = try await asset.loadTracks(withMediaType: .video) guard let track = trackArray.first else { throw IONCAMRMetadataError.noVideoTrack } guard let urlMetadata = url.metadata else { throw IONCAMRMetadataError.urlConversionError } - let naturalSize: CGSize = if #available(iOS 15, *) { - try await track.load(.naturalSize) - } else { - track.naturalSize - } + let naturalSize = try await track.load(.naturalSize) let duration = Int(CMTimeGetSeconds(durationProperty).rounded()) let format = url.pathExtension.lowercased() let creationDate = urlMetadata.date @@ -53,7 +42,7 @@ final class IONCAMRMediaResultGenerator: IONCAMRMetadataGetterDelegate { extension IONCAMRMediaResultGenerator: IONCAMRThumbnailGeneratorDelegate { func getImage(from videoURL: URL, _ completion: @escaping (UIImage?) -> Void) { DispatchQueue.global().async { // run this on background - let asset = AVAsset(url: videoURL) + let asset = AVURLAsset(url: videoURL) let avAssetImageGenerator = AVAssetImageGenerator(asset: asset) avAssetImageGenerator.appliesPreferredTrackTransform = true // correct thumbnail orientation let thumnailTime = CMTimeMake(value: 2, timescale: 1) // time of the video to be used as a thumbnail diff --git a/Sources/IONCameraLib/Interfaces/IONCAMRPlayerBehaviour.swift b/Sources/IONCameraLib/Interfaces/IONCAMRPlayerBehaviour.swift index 9177ccc..399192e 100644 --- a/Sources/IONCameraLib/Interfaces/IONCAMRPlayerBehaviour.swift +++ b/Sources/IONCameraLib/Interfaces/IONCAMRPlayerBehaviour.swift @@ -22,28 +22,27 @@ final class IONCAMRPlayerBehaviour: NSObject, IONCAMRPlayerDelegate { func playVideo(_ url: URL) async throws { // Resolve the URL in case the app sandbox path has changed let resolvedURL = try resolveVideoURL(url) - let asset = AVAsset(url: resolvedURL) + let asset = AVURLAsset(url: resolvedURL) - let isPlayable: Bool = if #available(iOS 15, *) { - try await asset.load(.isPlayable) - } else { - asset.isPlayable - } + let isPlayable = try await asset.load(.isPlayable) if isPlayable { - DispatchQueue.main.async { - let player = AVPlayer(url: resolvedURL) - let playerViewController = AVPlayerViewController() - playerViewController.player = player - self.coordinator.present(playerViewController) - - player.play() - } + await presentPlayer(for: resolvedURL) } else { throw IONCAMRError.playVideoIssue } } + @MainActor + private func presentPlayer(for url: URL) { + let player = AVPlayer(url: url) + let playerViewController = AVPlayerViewController() + playerViewController.player = player + coordinator.present(playerViewController) + + player.play() + } + private func resolveVideoURL(_ url: URL) throws -> URL { // Check if the file exists at the given URL if FileManager.default.fileExists(atPath: url.path) { diff --git a/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoThumbnailView.swift b/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoThumbnailView.swift index 57d7f6f..a52af98 100644 --- a/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoThumbnailView.swift +++ b/Sources/IONCameraLib/Interfaces/PhotoLibrary/IONCAMRPhotoThumbnailView.swift @@ -59,7 +59,7 @@ struct IONCAMRPhotoThumbnailView: View { } } // We need to use the task to work on a concurrent request to load the image from the photo library service, which is asynchronous work. - .taskOperation { + .task(priority: .userInitiated) { await loadImageAsset() } // Finally, when the view disappears, we need to free it up from the memory @@ -82,22 +82,3 @@ extension IONCAMRPhotoThumbnailView { image = Image(uiImage: uiImage) } } - -extension View { - func taskOperation(priority: TaskPriority = .userInitiated, _ action: @escaping @Sendable () async -> Void) -> some View { - if #available(iOS 15, *) { - return task(priority: priority, action) - } else { - return taskiOS14(priority: priority, action) - } - } - - @available(iOS, deprecated: 15.0, message: "This extension is no longer necessary. Use API built into SDK") - func taskiOS14(priority: TaskPriority = .userInitiated, _ action: @escaping @Sendable () async -> Void) -> some View { - onAppear { - Task(priority: priority) { - await action() - } - } - } -}