草庐IT

ios - 当具有不同值的同一类对象作为数据源传递时,为什么不重新呈现 View

coder 2023-09-07 原文

我在探索 SwiftUI 时遇到了一些我不太明白的事情。

我已经创建了一个容器 View ,可以按照 this 中的描述获取数据发布,但我没有完全更改渲染 View 中引用的对象,而是加载了它的一些属性。

加载器是容器 View 观察的ObservableObject。当加载程序指示它(的值)已更改时,容器 View 重新加载其 body 属性并显示带有新数据的渲染 View 。但是,当需要加载的对象是一个类时,并不是所有的body属性中的 subview 都会重新加载。

这是我实现的一些“伪”代码。

protocol ValueLoader: Combine.ObservableObject {
    associatedtype Value

    var data: Value { get set }
    func load()
}

struct ValueLoadingContainerView<ValueConsumer: View, 
                                 ValueContainer: ValueLoader>: View {
    @ObservedObject var valueLoader: ValueContainer
    let containedView: (ValueContainer.Value) -> ValueConsumer

    init(_ loader: ValueContainer, 
         @ViewBuilder contained: @escaping (ValueContainer.Value) -> ValueConsumer) {
        self.valueLoader = loader
        self.containedView = contained
    }

    var body: some View {
        containedView(valueLoader.data)
            .onAppear(perform: load)
    }

    private func load() {
        self.valueLoader.load()
    }
}
class Object {
    let id: String
    var title: String?

    func load(from ...) {
        self.title = ...
    }
}
struct ConcreteLoader: ValueLoader {
    @Published var data: Object

    func load() {
        guard shouldLoad() else { return }  // To prevent infinite recursion
        ...
        // self.objectWillChange is synthesised by conforming to 
        // ObservableObject and having a property with @Published
        self.objectWillChange.send()          
        self.data.load(from: ...)
    }
}

struct ObjectRenderingView: View {
    let object: Object

    var body: some View {
        Text(object.title ?? "ObjectRenderingView is waiting...")
    }
}
let object = Object(id: "1", title: nil)

ValueLoadingContainer(ConcreteLoader(object), 
                      contained: { obj in
                          Text(obj.title ?? "Text is waiting...")     // 1
                          Divider()
                          ObjectRenderingView(object: obj)   // 2
                      })

当加载器加载了 object 的属性时,它再次调用传递给对象的 @ViewBuilder 闭包,但现在它的属性被加载了。

如果我添加 print 语句,我清楚地看到 contained @ViewBuilder 闭包被调用了两次:一次使用卸载的对象,一次与加载的对象。这些是同一个对象,但第二次加载了属性。

Text 标签 (1) 已正确更新,从“Text is waiting...”更改为实际标题,但 ObjectRenderingView (2) 没有更新其 subview 。

使用新数据调用 ObjectRenderingViewinit,但从未访问 body 属性。这向我表明 SwiftUI 认为数据没有改变并且不需要重新渲染。

我想我明白为什么它不起作用:obj 的身份没有改变,所以 SwiftUI 认为 ObjectRenderingView 不需要重新加载。由于值 obj.title 的标识已从 nil 更改为实际标题,因此重新加载 Text View 。我不知道的是如何让 SwiftUI 也重新加载 ObjectRenderingView

谢谢!

最佳答案

应该是值类型。请查看 Xcode 中 ObservedObject 的文档。

If Value is not value semantic, the updating behavior for any views that make use of the resulting Binding is unspecified.

关于ios - 当具有不同值的同一类对象作为数据源传递时,为什么不重新呈现 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57322150/

有关ios - 当具有不同值的同一类对象作为数据源传递时,为什么不重新呈现 View的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  4. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  5. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  6. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  7. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  8. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  9. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  10. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

随机推荐