ObservableObject研究——想说爱你不容易 如想获得更好的阅读体验,可以访问我的博客www.fatbobman.com 本文主要研究在SwiftUI中,采用单一数据源(Single Source of Truth)的开发模式,ObservableObject是否为最佳选择。 最后提供了一个仍采用单一数据源设计思路但完全弃用ObservableObject的方式。 恶化的原因主要有以下几点: 1.对于遵循ObservableObject对象的依赖注入时机2.View的精细化3.依赖通知接口唯一性。 对于遵循ObservableObject对象的依赖注入时机 在 @State研究 中的 什么时候建立的依赖?
五个数据流工具 可以通过它们建立数据和视图的依赖关系 Property @State @Binding ObservableObject @EnvironmentObject 注意:后面四种使用 Swift ,要想建立依赖关系就要用 ObservableObject,与之配合的是@ObservedObject和@Published。 @Published 是 Xcode11 beta5 之后新增的代理属性,此属性如果用在 ObservableObject 内,一旦修饰的属性发送了变化,会自动触发 ObservableObject 的 ObservableObject 是一个协议,必须要类去实现该协议。 ObservableObject 适用于多个 UI 之间的同步数据。 // 和@ObservableObject一样 class User: ObservableObject { @Published var name = "" @Published var
比如我们定义的数据结构Model,前提是 @Published 要在 ObservableObject 下使用 然后用 @ObservedObject 来引用这个对象,当然@State 不会报错,但是无法更新 class BaseModel: ObservableObject{ @Published var name:String = "" } struct ContentView: View{ :不是 如果层次再深一点的model 还是有bug,触发不了 4.总结以及解决方案 /// 既然我们知道View 跟 状态绑定的关系 /// 是以第一继承ObservableObject 类 下的属性( 字段)更新来更新视图的 /// 那我们可以给 ObservableObject 加一个 无关紧要的字段,然后编写一个方法,来通知更新 class BaseobservableObject: ObservableObject 类的 /// 所以,直接继承 ObservableObject 下的属性(字段)没更新,就不会更新View /// 最简单的解决办法就是 更新直接继承 ObservableObject(父对象) 里面的随便一个属性
@StateObject 专门用于管理符合 ObservableObject 协议的实例。 标注的对象实例在视图的整个生命周期中保持唯一,即使视图更新,对象实例也不会重新创建。 实例之间创建关联的属性包装器,主要用于在视图存续期内引入外部的 ObservableObject 实例。 // 定义一个符合 ObservableObject 协议的数据模型 class DataModel: ObservableObject, Identifiable { let id = UUID 适用于构建复杂的视图层级,其中多个视图需要访问同一个 ObservableObject 实例。 总结 @StateObject、@ObservedObject 和 @EnvironmentObject 专用于关联符合 ObservableObject 协议的实例。
访问我的博客 www.fatbobman.com[1] 可以获得更好的阅读体验 本文将对 @Published 与符合 ObservableObject 协议的类实例之间的沟通机制做以介绍,并通过三个示例 class Weather:ObservableObject { // 遵循 ObservableObject @Published var temperature: Double init class Weather:ObservableObject { var temperature: Double{ // 没有使用 @Published 进行标记 willSet 例如下面的代码,我们不会收到任何提示: class RefObject { var count = 0 init() {} } class Test: ObservableObject 因此,我们可以使用如下的代码在 SwiftUI 中统一管理 UserDefaults : class Defaults: ObservableObject { @AppStorage("name
= require("framework.ObservableObject") local ObservableDictionary = require("framework.ObservableDictionary ") --- --创建一个Account子视图模型 --@module Account local Account = class("Account",ObservableObject) function Account:ctor(t) --执行父类ObservableObject的构造函数,这个重要,否则无法监听数据改变 Account.super.ctor(self,t) if not ( ) function DatabindingViewModel:ctor(t) --执行父类ObservableObject的构造函数,这个重要,否则无法监听数据改变 DatabindingViewModel.super.ctor = require("framework.ObservableObject") local ObservableDictionary = require("framework.ObservableDictionary
@Published属性 class ContentViewModel: ObservableObject { @Published var changingColor = Color.blue .foregroundColor(viewModel.changingColor) } } onchange Modifier class ContentViewModel: ObservableObject value in degrees += 15 }) } } task Modifier class ContentViewModel: ObservableObject DataService.notificationName), object: nil) }) } } class ContentViewModel: ObservableObject
自定义UI class 假设,我们SwiftUI中的一个实现ObservableObject的类,其中被@Published装饰的属性需要自动运行在主线程。 我们只需要装饰@MainActor即可。 @MainActor class ListViewModel: ObservableObject { @Published private(set) var result: Result<[Item @MainActor class ListViewModel: ObservableObject { ...
添加 using 指令以使用新 API: using Microsoft.Toolkit.Mvvm; 这个包主要提供了如下的 Microsoft.Toolkit.Mvvm.ComponentModel ObservableObject CollectionRequestMessage AsyncCollectionRequestMessage ValueChangedMessage 可观察对象 public class UserVM : ObservableObject IncrementAgeCommand}" Content="年龄递增" /> </StackPanel> 对应的ViewModel中添加命令及响应的事件 public class UserVM : ObservableObject App.Current.Services.GetService(typeof(IUserService)); 这样是不是感觉还麻烦了 但是如果我们的ViewModel是这样的 public class UserVM : ObservableObject
各个组件 2.1 ObservableObject ObservableObject 实现了 INotifyPropertyChanged 和INotifyPropertyChanging,并触发 PropertyChanged public class User : ObservableObject { private string name; public string Name { 下面的代码使用 ObservableObject 和 RelayCommand 展示一个基本的 ViewModel: public class MyViewModel : ObservableObject 2.5 ObservableRecipient ObservableRecipient 继承了 ObservableObject 并支持从 Messenger 接收信息,可通过 IsActive 属性激活或停用
此外,在 SwiftUI 中,引用类型的数据源(Source of Truth)采用了基于 Combine 框架的 ObservableObject 协议实现。 如何声明可观察对象 使用 Combine 框架,我们可以这样声明一个可被观察的引用类型: class Store: ObservableObject { @Published var firstName 可以预期,在开发 iOS 17+ 应用程序时,通过 Observation 框架声明的可观察对象和遵循 ObservableObject 协议的可观察对象,同时出现的场景将越来越少。 在视图中 @Obervable 与 ObservableObject 可以共存吗 可以。在一个视图中,可以同时存在以不同的方式声明的可观察对象。 由于 @Published 仅支持值类型,因此对于遵守 ObservableObject 协议的可观察对象,很难实现类似的嵌套逻辑: class A:ObservableObject { @Published
首先定义几个Model
public class School : ObservableObject
{
private bool _isOpen;
///
@Observable Macro performance increase over ObservableObject[7] Antoine van der Lee[8] 本文深入探讨了在 SwiftUI 中应用@Observable 宏以提升性能,并将其与 ObservableObject 进行了深入比较。 文章详尽地阐述了如何从 ObservableObject 和@Published 平稳过渡到@Observable 的方法,并着重讨论了采用@Observable 带来的优势,尤其是在管理多个视图模型属性时 Yasuhito Nagatomo: https://twitter.com/AtarayoSD [7] @Observable Macro performance increase over ObservableObject
Foundationimport Combineimport UIKit现在我们需要把当前保存用户设置的环境变量添加上一个属性,它可以使其他类监听到属性的改变现在环境变量需要有一个监听对象class UserSetting: ObservableObject sinks = [AnyCancellable]() var values = [Any]() private init() {} func register<T: ObservableObject ) } } update() } }@propertyWrapper struct Gloabl <ObjectiveType: ObservableObject
import StoreKit @MainActor final class Store: ObservableObject { @Published private(set) var products @MainActor final class Store: ObservableObject { // ... @MainActor final class Store: ObservableObject { @Published private(set) var activeTransactions: @MainActor final class Store: ObservableObject { @Published private(set) var activeTransactions:
import SwiftUI @MainActor class ViewModel: ObservableObject { } struct ContentView: View { // 警告 import SwiftUI @MainActor class ViewModel: ObservableObject { } struct ContentView: View { @StateObject
ObservableObject:与 SwiftUI 一起使用,符合ObservableObject协议的对象可以提供 Publisher 。
SwiftUI 的 @Observable 宏并非 ObservableObject 的完美替代品 (SwiftUI's Observable macro is not a drop-in replacement for ObservableObject)[5] jesse squires[6] 因其更精准的响应机制,@Observable 宏在 SwiftUI 框架中被视为 ObservableObject seen): https://t.ly/dhhQq [4] Filip Němeček: https://x.com/nemecek_f [5] SwiftUI 的 @Observable 宏并非 ObservableObject 的完美替代品 (SwiftUI's Observable macro is not a drop-in replacement for ObservableObject): https://t.ly/
在向您展示一些代码之前,还有最后一件事:环境对象使用您已经学过的ObservableObject协议,SwiftUI将自动确保共享同一环境对象的所有视图在更改时都会更新。 首先,这是我们可以使用的一些基本数据: class User: ObservableObject { @Published var name = "Taylor Swift" } 如您所见,使用 ObservableObject和@Published就像我们以前学到的那样——您积累的所有知识将继续得到回报。
注入到现有类 一般来说,MVVM Toolkit source generators 需要在 ObservableObject 的派生类中使用,例如: public partial class TestModel : ObservableObject 但如果你的类已经继承了其它类,MVVM Toolk source generators 也允许你使用它的功能,方法是添加上 INotifyPropertyChangedAttribute INotifyPropertyChanged 接口的类中使用,即下面这种代码不能编译通过: [INotifyPropertyChanged] public partial class TestModel: ObservableObject