swift - StateObject 的 SwiftUI 工具栏操作导致帧速率下降
问题描述
我有一个相当直接的 swift UI 视图,它允许你拖动一个形状。
我注意到,每当我有一个工具栏动作,该动作具有捕捉我观察到的对象的动作时,grid
帧速率就会显着下降。
这是下面的代码,状态对象当前在操作中 ( grid.snapEnabled.toggle()
)
func makeItem() -> SGGridItem {
SGGridItem(id: UUID(), rect: CGRect(origin: .init(x: 250, y: 250), size: .init(width: 50, height: 50)))
}
struct ContentView: View {
@StateObject var grid = SGGridState(items: [
makeItem(),
makeItem(),
makeItem(),
makeItem(),
makeItem(),
makeItem()
])
var body: some View {
SGGridCanvas(grid:grid) {
SGGridView(grid: grid)
}.frame(maxWidth:.infinity, maxHeight: .infinity)
.toolbar(content: {
ToolbarItem(placement: .principal) {
Button(action: { grid.snapEnabled.toggle() }) {
Image(systemName: "square.grid.3x3.topleft.fill").opacity(grid.snapEnabled ? 1 : 0.5)
}
}
})
.onAppear {
grid.globalGridItemPadding = 5
grid.globalGridItemCornerRadius = 5
}
}
}
在此 GIF 中,您可以看到明显的滞后,因为被拖动的形状跟随在鼠标光标后面。
但是,如果我现在将工具栏操作更改为像这样的空闭包
ToolbarItem(placement: .principal) {
Button(action: { }) {
Image(systemName: "square.grid.3x3.topleft.fill").opacity(grid.snapEnabled ? 1 : 0.5)
}
}
然后如您所见,视图现在按预期执行(形状完全跟随鼠标)。
在闭包中捕获状态对象时,我打算在这里做一些特别的事情吗?
这是 swift UI 中固有的性能问题,还是我需要以某种方式改变我的结构?
解决方案
没有太多运气直接解决这个问题。
唯一可行的方法是使用通知中心将状态对象与操作分离。
下面的一些东西起作用了。
public extension Notification.Name {
static let SGGridStateSnapEnableToggle = Notification.Name("SGGridStateSnapEnableToggle")
}
public class SGGridState: ObservableObject {
@Published public var snapEnabled: Bool = true
init() {
NotificationCenter.default.addObserver(self, selector: #selector(self.snapEnabledToggle), name: .SGGridStateSnapEnableToggle, object: nil)
}
@objc public func snapEnabledToggle() {
snapEnabled.toggle()
}
}
然后在原始工具栏操作中,我们可以发布通知,状态对象将其拾取并切换它自己的 Published 属性。
ToolbarItem(placement: .principal) {
Button(action: {
NotificationCenter.default.post(name: .SGGridStateSnapEnableToggle, object: nil)
}) {
Image(systemName: "square.grid.3x3.topleft.fill")
}
}
不理想,但它有效。
推荐阅读
- swift - 具有标识符的后台 URLSession 已存在
- dart - 如何在flutter中显示填充下的数据?
- javascript - 将 Javascript CSS 连接到 CSS
- sql-server-2012 - 字段满足特定条件时的电子邮件提醒
- mysql - join sql查询单行结果
- python - 将 s3curl.pl 的使用移植到 Python
- r - Xlsx 库将无法在 R 中正确加载
- ms-access - 无法从其他子表单刷新子表单
- java - Spring Boot OAuth 2:登录后匿名用户
- spring-mvc - 泽西 @BeanParam,Spring mvc 中的 @HeaderParam 替代品