将 NSFont 与 AttributeContainer 结合使用

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

创建用于 AppKit 的

AttributedString
时,我收到一条警告,指出
NSFont
不是
Sendable
:

    var container = AttributeContainer()
    container.appKit.foregroundColor = .red
    container.appKit.font = .systemFont(ofSize: mySize)
//  ^ Conformance of 'NSFont' to 'Sendable' is unavailable

警告是正确的,

NSFont
不是
Sendable
,那么有没有办法在不关闭并发警告的情况下完成此任务?在审核
Sendable
一致性方面,AppKit 远远落后于 SwiftUI 和 UIKit,但我对此无能为力。将
Foundation
的导入标记为
@preconcurrency
没有任何效果。快速测试项目表明字体设置正确并且可以在
NSTextView
中使用。我只是不想一直盯着这些警告,直到苹果开始改进 AppKit(从历史上看,可能需要相当长的时间)。

swift appkit attributedstring
1个回答
0
投票

我建议您,尽管 NSFont 不是可发送的,但这并不一定意味着跨线程使用它不安全。截至 iOS SDK 的当前状态,它还没有经过正式的线程安全审核(我认为——还没有检查文档)。

您正确地观察到 AppKit 在采用新的 Swift 并发功能方面落后于 SwiftUI 和 UIKit。必须了解 Sendable 协议是一种编译时检查,它不会使类型成为线程安全的;它仅表明该类型在设计时考虑了线程安全。

当使用像 NSFont 这样不可发送的类型时,以注意并发性的方式使用它们是至关重要的。大多数情况下,这意味着仅在主线程上使用它们,因为 AppKit 和 UIKit 并非设计为线程安全的。

要抑制有关 NSFont 不可发送的警告,您可以在 NSFont 周围创建一个包装器,以断言其在主线程上的使用情况。这是一个例子:

struct MainThreadFont: Sendable {
    private let font: NSFont

    init(_ font: NSFont) {
        assert(Thread.isMainThread)
        self.font = font
    }

    var value: NSFont {
        assert(Thread.isMainThread)
        return font
    }
}

你可以像这样使用它:

var container = AttributeContainer()
container.appKit.foregroundColor = .red
container.appKit.font = MainThreadFont(.systemFont(ofSize: mySize)).value

这种方法确保 NSFont 只能从主线程访问,提供一定程度的安全性。然而,在 Apple 将 Sendable 一致性添加到 NSFont 之前,这只是一种解决方法。

一如既往,您应该彻底测试并发代码,以确保它在所有情况下都能正确运行。

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