纯Swift并发

vd8tlhqk  于 2023-01-29  发布在  Swift
关注(0)|答案(4)|浏览(134)

我遇到的所有提供Swift并发功能的库要么依赖于Objective-C库,要么是基于C的GCD的 Package 器(iOS和OSX)。
我只是想知道是否有人知道一个纯粹的Swift并发库?没有依赖性。或者如果没有,我们怎么去做一个呢?

r55awzrz

r55awzrz1#

Swift语言还没有支持并发的结构,有传言说这些结构将被添加到该语言的未来版本中,但同时,我认为没有操作系统的支持,你无法做到这一点。
由于GCD块是Swift闭包,因此GCD在Swift中提供了相当干净的并发解决方案,但它不依赖于平台(至少在苹果生态系统之外是这样)。

编辑:

我想您可以使用POSIX编写一个并发库,该库可以在所有POSIX兼容的操作系统上运行,但Windows并不真正兼容POSIX,因此这可能也不是一个完美的解决方案。

编辑#2:

在Swift 3中,GCD接口已经被清理,变得更加"敏捷"。现在有了一个Dispatch类,它有类方法来做以前使用全局函数的事情。

yvfmudvl

yvfmudvl2#

您可以创建一个简单的基于队列的调度抽象,如下所示:

protocol OperationQueue {
    var suspended: Bool { get set }
    var operationCount: Int { get }
    func addOperationWithBlock(block: () -> Void)
    func cancelAllOperations()
    func waitUntilAllOperationsAreFinished()
}

然后,在OS X(或任何其他Apple平台)上,您可以直接使用GCD:

extension NSOperationQueue: OperationQueue { }

在所有其他系统上,您可以创建自己的实现:

class POSIXOperationQueue: OperationQueue { /* implementation with pthread */ }
class Win32OperationQueue: OperationQueue { /* implementation with Win32 API */ }
bxpogfeg

bxpogfeg3#

Swift 5.5开始,Swift现在支持内置语言特性的并发,如async/await、任务、任务组、参与者和结构化并发。

mklgxw1f

mklgxw1f4#

    • 快速并发**

Official doc
Swift内置了对以结构化方式编写异步和并行代码的支持。
Concurrency vs Parallelism(https://stackoverflow.com/a/63744581/4770877)
Sync vs Async(https://stackoverflow.com/a/75225609/4770877)
它是一种从Swift v5.5到iOS v15和v13的向后兼容性
解决了:

  • 回叫地狱
  • 易于读取、写入和支持

高层结构:

  • await/async(func,let)标记,用于识别异步函数并运行它们。您可以在回调中使用withCheckedThrowingContinuationwithCheckedContinuation来支持await/async
  • Task-创建一个并发环境,其中允许await/async,它在创建后立即启动,可以在创建时设置优先级并可以取消,因此具有自己的生命周期-当前状态。Task.init(priority:operation:)创建非结构化并发(没有父任务)
  • Task Group-允许运行并行(比await async let更具动态性)任务并完成所有任务-任务组已完成。使用TaskGroup.addTaskawait async let时会创建结构化并发,因为它在任务和taskGroup之间具有显式父子关系
  • Actor(https://stackoverflow.com/a/75137101/4770877)-在并发环境中的tasks之间共享数据,以防止数据争用

示例:

func runImageTask() {
    let imageSaver = ImageSaver()
    Task.init {
        do {
            let url = URL(string: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_dark_color_272x92dp.png")!
            guard let image = try await self.downloadImage(from: url) else { return }
            try await imageSaver.storeImage(image)
            guard let transformedImage = try await self.transformImage(image) else { return }
            try await imageSaver.storeImage(transformedImage)
            
            self.showImage(transformedImage)
        } catch {
            print("error:\(error)")
        }
    }
}

func downloadImage(from url: URL) async throws -> UIImage? {
    let (data, response) = try await URLSession.shared.data(from: url)
    return UIImage(data: data)
}

func transformImage(_ image: UIImage) async throws -> UIImage? {
    return try await withCheckedThrowingContinuation { continuation in
        DispatchQueue.global().async {
            UIGraphicsBeginImageContext(image.size)
            image.draw(at: CGPoint.zero)

            guard let context = UIGraphicsGetCurrentContext() else {
                continuation.resume(with: .failure(NSError(domain: "context is nil", code: 1)))
                return
            }

            context.setStrokeColor(UIColor.green.cgColor)
            context.setLineWidth(5)
            context.addEllipse(in: CGRect(x: 50, y: 50, width: 50, height: 50))
            context.drawPath(using: .stroke)

            let transformedImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
             
            continuation.resume(with: .success(transformedImage))
        }
    }
    
}

func showImage(_ image: UIImage) {
    self.imageView.image = image
}

class ImageSaver: NSObject {
    var continuation: CheckedContinuation<Void, Error>? = nil
    
    func storeImage(_ image: UIImage) async throws {
        return try await withCheckedThrowingContinuation { continuation in
            self.continuation = continuation
            UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveCompleted), nil)
        }
    }

    @objc func saveCompleted(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        let result: Result<(), Error>
        if let error = error {
            result = .failure(error)
        } else {
            result = .success(())
        }
        self.continuation?.resume(with: result)
    }
}

Kotlin Coroutine(https://stackoverflow.com/a/65169350/4770877)

相关问题