diff --git a/mobile/ios/Runner/Images/ImageProcessing.swift b/mobile/ios/Runner/Images/ImageProcessing.swift index 2270bbffac..686a3464a7 100644 --- a/mobile/ios/Runner/Images/ImageProcessing.swift +++ b/mobile/ios/Runner/Images/ImageProcessing.swift @@ -1,7 +1,12 @@ import Foundation enum ImageProcessing { - static let queue = DispatchQueue(label: "thumbnail.processing", qos: .userInitiated, attributes: .concurrent) - static let semaphore = DispatchSemaphore(value: ProcessInfo.processInfo.activeProcessorCount * 2) + static let queue = { + let q = OperationQueue() + q.name = "thumbnail.processing" + q.qualityOfService = .userInitiated + q.maxConcurrentOperationCount = ProcessInfo.processInfo.activeProcessorCount * 2 + return q + }() static let cancelledResult = Result<[String: Int64]?, any Error>.success(nil) } diff --git a/mobile/ios/Runner/Images/LocalImagesImpl.swift b/mobile/ios/Runner/Images/LocalImagesImpl.swift index 303ff5bc33..f0710bf75f 100644 --- a/mobile/ios/Runner/Images/LocalImagesImpl.swift +++ b/mobile/ios/Runner/Images/LocalImagesImpl.swift @@ -4,7 +4,7 @@ import MobileCoreServices import Photos class LocalImageRequest { - weak var workItem: DispatchWorkItem? + weak var operation: Operation? var isCancelled = false let callback: (Result<[String: Int64]?, any Error>) -> Void @@ -50,7 +50,7 @@ class LocalImageApiImpl: LocalImageApi { }() func getThumbhash(thumbhash: String, completion: @escaping (Result<[String : Int64], any Error>) -> Void) { - ImageProcessing.queue.async { + ImageProcessing.queue.addOperation { guard let data = Data(base64Encoded: thumbhash) else { return completion(.failure(PigeonError(code: "", message: "Invalid base64 string: \(thumbhash)", details: nil)))} @@ -66,16 +66,7 @@ class LocalImageApiImpl: LocalImageApi { func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, preferEncoded: Bool, completion: @escaping (Result<[String: Int64]?, any Error>) -> Void) { let request = LocalImageRequest(callback: completion) - let item = DispatchWorkItem { - if request.isCancelled { - return completion(ImageProcessing.cancelledResult) - } - - ImageProcessing.semaphore.wait() - defer { - ImageProcessing.semaphore.signal() - } - + let operation = BlockOperation { if request.isCancelled { return completion(ImageProcessing.cancelledResult) } @@ -180,9 +171,9 @@ class LocalImageApiImpl: LocalImageApi { } } - request.workItem = item + request.operation = operation Self.add(requestId: requestId, request: request) - ImageProcessing.queue.async(execute: item) + ImageProcessing.queue.addOperation(operation) } func cancelRequest(requestId: Int64) { @@ -201,8 +192,8 @@ class LocalImageApiImpl: LocalImageApi { requestQueue.async { guard let request = requests.removeValue(forKey: requestId) else { return } request.isCancelled = true - guard let item = request.workItem else { return } - if item.isCancelled { + guard let operation = request.operation else { return } + if operation.isCancelled { cancelQueue.async { request.callback(ImageProcessing.cancelledResult) } } } diff --git a/mobile/ios/Runner/Images/RemoteImagesImpl.swift b/mobile/ios/Runner/Images/RemoteImagesImpl.swift index f2a0c37254..7c69acba76 100644 --- a/mobile/ios/Runner/Images/RemoteImagesImpl.swift +++ b/mobile/ios/Runner/Images/RemoteImagesImpl.swift @@ -73,10 +73,7 @@ class RemoteImageApiImpl: NSObject, RemoteImageApi { return request.completion(.failure(PigeonError(code: "", message: "No data received", details: nil))) } - ImageProcessing.queue.async { - ImageProcessing.semaphore.wait() - defer { ImageProcessing.semaphore.signal() } - + ImageProcessing.queue.addOperation { if request.isCancelled { return request.completion(ImageProcessing.cancelledResult) }