Swift'de, eşzamansız kod için OperationQueue
kullanmak tam bir cehennem gibi görünebilir çünkü aslında, eşzamanlı kodlarının derlenmesi tamamlanırsa Operations
tamamlanmış kabul edilir.
Başka bir deyişle, aşağıda açıklanan örneğin derlenmesi bozuk bir yürütme emri verecektir çünkü asenkron kod yürütüldüğünde Operation
kendisi zaten tamamlanmış olacaktır.
let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 operationQueue.addOperation { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { print("First async operation complete") } print("First sync operation complete") } operationQueue.addOperation { DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { print("Second async operation complete") } print("Second sync operation complete") }
Bu kod yazdırılacaktır:
First sync operation complete Second sync operation complete First async operation complete Second async operation complete
Ancak bu kısıtlamaları aşmanın bir yolu var. Sorunun nasıl çözüleceğini anlamak için Operation
arka planda nasıl çalıştığını anlamanız gerekir.
Operation
kendisinde, operasyonun yaşam döngüsünü takip edebileceğiniz dört bayrak bulunur:
isReady
— Operation
şu anda gerçekleştirilip gerçekleştirilemeyeceğini gösterir.
isExecuting
—bir Operation
şu anda devam edip etmediğini gösterir.
isFinished
Operation
şu anda tamamlanıp tamamlanmadığını gösterir.
isCancelled
Operation
iptal edilip edilmediğini gösterir.
Teorik olarak, Operation
Operation
eşzamansız olarak yürütülmeden önce isFinished
durumuna girer, bu nedenle, Operation
yaşam döngüsünü yönetebileceğimiz bir teknik geliştirmemiz gerekir.
Bu olasılık, Operation
alt sınıflara ayırarak ve ayrıca start
/ cancel
yöntemlerinin yanı sıra operasyonun yaşam döngüsünün oluşturulduğu tüm bayrakların yeniden tanımlanmasıyla çözülebilir.
İşte kod:
public class AsyncOperation: Operation { // MARK: Open override open var isAsynchronous: Bool { true } override open var isReady: Bool { super.isReady && self.state == .ready } override open var isExecuting: Bool { self.state == .executing } override open var isFinished: Bool { self.state == .finished } override open func start() { if isCancelled { state = .finished return } main() state = .executing } override open func cancel() { super.cancel() state = .finished } // MARK: Public public enum State: String { case ready case executing case finished // MARK: Fileprivate fileprivate var keyPath: String { "is" + rawValue.capitalized } } public var state = State.ready { willSet { willChangeValue(forKey: newValue.keyPath) willChangeValue(forKey: state.keyPath) } didSet { didChangeValue(forKey: oldValue.keyPath) didChangeValue(forKey: state.keyPath) } } }
Operation
aldığımız alt sınıf temeldir ve manuel olarak zorla tamamlamamıza olanak tanır.
Tamamlama bloklarıyla çalışmak için başka bir alt sınıf oluşturmalısınız. Ancak bu, Operation
değil AsyncOperation
öğesinin bir alt sınıfı olacaktır.
public typealias VoidClosure = () -> Void public typealias Closure<T> = (T) -> Void public class CompletionOperation: AsyncOperation { // MARK: Lifecycle public init(completeBlock: Closure<VoidClosure?>?) { self.completeBlock = completeBlock } // MARK: Public override public func main() { DispatchQueue.main.async { [weak self] in self?.completeBlock? { DispatchQueue.main.async { self?.state = .finished } } } } // MARK: Private private let completeBlock: Closure<VoidClosure?>? }
Bu alt sınıf, Operation
bir kapanış geçirmemize izin verecek ve ardından Operation
tamamlanacak.
Bu tür bir işlemi pratikte deneyelim:
let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 operationQueue.addOperation( CompletionOperation { completion in DispatchQueue.main.asyncAfter(deadline: .now() + 1) { print("First async operation complete") completion?() } print("First sync operation complete") } ) operationQueue.addOperation( CompletionOperation { completion in DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { print("Second async operation complete") completion?() } print("Second sync operation complete") } )
Sonuç olarak, Operations
eşzamanlı yürütülmesini sağlamayı başardık:
First sync operation complete First async operation complete Second sync operation complete Second async operation complete
Benimle iletişime geçmekten çekinmeyin
Burada da yayınlandı