一发入魂:极简解决 SwiftUI 复杂视图未能正确刷新的问题(下)

概述

各位似秃非秃小码农们都知道,在 SwiftUI 中视图是状态的函数,这意味着状态的改变会导致界面被刷新。

但是,对于有些复杂布局的 SwiftUI 视图来说,它们的界面并不能直接映射到对应的状态上去。这就会造成一个问题:状态的改变并没有及时的引起 UI 的变化。

如上图所示:无论英雄挑战关卡的结果是成功还是失败,在视图的显示中都没有体现出来。这该如何是好呢?

在本篇博文中,您将学到如下内容:

  1. 一发入魂:三行代码搞定所有问题!

相信学完本课后,大家都会掌握只需寥寥几行代码就让 SwiftUI 复杂视图乖乖听话的奥义!

那还等什么呢?Let‘s go!!!;)


4. 一发入魂:三行代码搞定所有问题!

对 SwiftUI 开发范式略有了解的小伙伴们都清楚,SwiftUI 框架简洁、稳定和高效的诸多好处都受益于响应式编程思想。

它通过数据绑定(如 @State、@Binding、@ObservedObject 等)实现 UI 与数据的自动同步,这主要体现在:

  • 数据驱动:当数据状态变化时,界面自动更新(如 @Published 属性包装器触发视图刷新);
  • 单向数据流:数据从模型层流向视图层,确保逻辑清晰且避免副作用;

而数据绑定的核心就是状态!其诀窍就在于:当状态自身发生改变时,它会及时的触发相关视图界面的刷新。

长话短说,在 SwiftUI 中对于引用(Class)状态对象来说,会有一个类型为 ObservableObjectPublisher 的发布器对象被自动合成,它就是 objectWillChange 对象:

这个对象是谁免费赠送给我们这些秃头码农的呢?你猜对了!它就是大名鼎鼎的 ObservableObject 协议:

你说巧不巧?在 CoreData 中,托管对象基类 NSManagedObject 恰好遵守 ObservableObject 协议,这意味着任何我们派生托管类的实例都可以与 objectWillChange 同舟共济:

在我们的 App 中,若 ObservableObject 可观察对象发生变化,则其 objectWillChange 发布器(Publisher)会立即发出“信号”,与此可观察对象绑定的 SwiftUI 视图会由此重新计算 body 内容,从而完成界面的刷新。

在了解了这一点之后,我们完全可以利用可观察对象中的 objectWillChange 发布器在任何时候控制特定视图的刷新,只需简单的让它发送消息就可以了:

Button {
    if try! hero.challengeStage() {
        try! hero.moveToNextStage()
    }
    
    stage.objectWillChange.send()    
} label: {
    Label("挑战关卡!", systemImage: "figure.fencing")
        .foregroundStyle(.white)
}

在上面的代码中,我们在英雄挑战关卡后,立即向关卡对象(Stage)的objectWillChange 发布器发送了一条消息,这会促使该 Stage 对象对应的视图被刷新:

同样,要想关卡挑战后父视图 WorldView 中英雄的挑战状态也得以顺利得到更新,我们只需再对 Word 托管对象如法炮制即可:

Button {
    if try! hero.challengeStage() {
        try! hero.moveToNextStage()
    }
    
    stage.objectWillChange.send()
    
    let world = try! World.getShared(context)
    world.objectWillChange.send()    
    
} label: {
    Label("挑战关卡!", systemImage: "figure.fencing")
        .foregroundStyle(.white)
}

如上所示,最终我们一共只需在挑战操作后增加 3 行代码,即可搞定 StageView 和 WorldView 中所有的刷新问题:

如您所见:当英雄挑战关卡成功返回到上层 WorldView 视图后,英雄(黄色的五角星)已经妥妥的位于下一关的 StageCell 中了,棒棒哒!💯

总结

在本篇博文中,我们讨论了仅需 3 行代码即可解决 SwiftUI 复杂视图不能及时刷新的小妙招,小伙伴们值得拥有。

感谢观赏,再会啦!8-)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容