如何以线程安全的方式观察UIPasteboard?

问题描述 投票:0回答:1

我有一个可观察类,它在 UIPasteboard 上有一个观察者。在尝试更新到 Swift 6 语言模式时,我无法从完成处理程序中改变状态,这是可以理解的。

@Observable
final class ImageClipboard {
    var images: [SelectableImage]
    
    init() {
        self.images = []
        
        NotificationCenter.default.addObserver(forName: UIPasteboard.changedNotification, object: nil, queue: .main) { _ in
            if let pasteboardImages = UIPasteboard.general.images {
                let newImages = pasteboardImages.map {
                    SelectableImage(image: $0)
                }
                
                self.images.append(contentsOf: pasteboardImages)
            }
        }
    }
}

我的偏好是使用异步机制来改变图像,否则使用一些同步机制。处理这个问题的最佳方法是什么?

swift concurrency swift-concurrency swift6
1个回答
0
投票

我认为在这种情况下,作为合并发布者 (

publisher(for:object:)
) 获取通知会更方便。

@Observable
class ImageClipboard {
    var images: [SelectableImage] = []
    @ObservationIgnored
    var cancellable: AnyCancellable?
    
    init() {
        cancellable = NotificationCenter.default.publisher(for: UIPasteboard.changedNotification).sink { _ in
            let images = UIPasteboard.general.images?.map { SelectableImage(image: $0) } ?? []
            self.images.append(contentsOf: images)
        }
    }
}

ImageClipboard
取消初始化时,发布者会自动取消。


还有

notifications(named:object:)
,你可以这样使用:

@Observable
@MainActor
class ImageClipboard {
    var images: [SelectableImage] = []
    
    func startMonitoringClipboard() async {
        for await _ in NotificationCenter.default.notifications(named: UIPasteboard.changedNotification) {
            let images = UIPasteboard.general.images?.map { SelectableImage(image: $0) } ?? []
            self.images.append(contentsOf: images)
        }
    }
}

那么在您看来,您应该在

startMonitoringClipboard
中调用
.task
:

SomeView()
    .task {
        await clipboard.startMonitoringClipboard()
    }

SomeView
消失时,任务将被取消。

© www.soinside.com 2019 - 2024. All rights reserved.