swift 使用NSFont和AttributeContainer

o2rvlv0m  于 7个月前  发布在  Swift
关注(0)|答案(4)|浏览(30)

在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完善(从历史上看,可能是相当长的一段时间)。
编辑:我使用的是Xcode 15b5。Xcode 14.3.1不显示警告。

jfgube3f

jfgube3f1#

您可以使用[NSAttributedString.Key : Any]字典初始化容器。这不显示警告

let container = AttributeContainer([.foregroundColor: Color.red, 
                                    .font: NSFont.systemFont(ofSize: mySize)])
2vuwiymt

2vuwiymt2#

似乎没有一个好的方法来处理这件事。我就这个问题提交了反馈(FB12885931),但是......你知道的。
有理由将NSFont标记为Sendable,因为它在Cocoa Text Architecture Guide中的记录如下:“字体对象是不可变的,所以在你的应用程序中从多个线程使用它们是安全的。”希望苹果很快会更彻底地审计AppKit的并发问题。

tag5nh1u

tag5nh1u3#

下面的代码消除了Xcode 15.0 beta 6中的警告:

var container = AttributeContainer()
    container.appKit.foregroundColor = .red
    // Produces a value of type `AttributeScopes.SwiftUIAttributes.FontAttribute.Value`
    container.appKit.font = .init(.systemFont(ofSize: mySize))
8mmmxcuj

8mmmxcuj4#

因误解编辑:
NSFont Package 在另一个类似MainThreadFont的结构中不会消除编译器警告,因为NSFont没有声明为Sendable。我疏忽了。
不幸的是,据我所知,这个问题没有一个完美的解决方案。现在,如果你确定你的NSFont在不同线程中的使用是安全的,你可能需要使用@unchecked Sendable属性来抑制警告,但是请谨慎使用,只有当你绝对确定线程安全时,因为这会绕过Swift的并发安全检查。
下面是一个示例:

struct UncheckedSendableFont: Sendable {
    @MainActor
    private let font: NSFont

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

    @MainActor
    var value: NSFont {
        return font
    }
}

然后这样使用:

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

这将防止并发警告出现。
请注意,这实际上告诉Swift忽略NSFont的Sendable一致性问题。只有当您完全确信使用NSFont不会导致任何并发问题时,才应该使用它。作为最佳实践,请始终确保仅在主线程上访问NSFont示例,并且在线程之间传递它们时要非常小心。

相关问题