首页 > 其他分享 >iOS 17:告别ObservableObject,迎接@Observable

iOS 17:告别ObservableObject,迎接@Observable

时间:2023-10-22 15:33:18浏览次数:33  
标签:Observable 17 Book ObservableObject book var view View

自iOS 17(iPadOS 17, macOS 14)之后,SwiftUI 提供了一种新的宏:@Observable
可以把它当做是 ObservableObject 的优化版。在系统版本允许的情况下,我们应该优先使用@Observable
@ObservableObservableObject更好的地方在于:

  1. 写法上更加简洁;
  2. 性能更优化。@Observable能精确到对象属性变化来更新view,也就是说,只有view读取的属性变化,才会触发view的刷新。而ObservableObject的更新是无差别的,无论view读取了ObservableObject对象的哪些属性,只要ObservableObject被视为变化,与之关联的view都会刷新。

对比修饰符

ObservableObject 搭配的修饰符有:

  1. @StateObject;
  2. @ObservedObject;
  3. @EnvironmentObject;

@Observable 搭配的修饰符有:

  1. @State;
  2. @Bindalbe;
  3. @Environment;

新的写法

代码引用自 官方示例

示例的界面层次:BookReaderApp > LibraryView > BookView > BookEditView

首先定义 @Observable对象,

@Observable class Library {
    var name = "sample library"
    var books: [Book] = [Book(), Book(), Book()] 
    @ObservationIgnored var hello = "hello" // @ObservationIgnored 用于标记属性为不可监听。使得该属性值的变化不触发view更新。
}

@Observable class Book: Identifiable {
    var title = "Sample Book Title"
    let id = UUID() 
}


如果只是想让界面及时刷新数据?

struct BookView: View {
    var book: Book     // 无需修饰符,view自动监听对象的属性变化
    var body: some View {
            Text(book.title)
    }
}

如果还想“绑定”属性,好让控件来修改属性?

struct BookView: View {
    @State var book: Book = Book()  // @State 修饰
    var body: some View {
          TextField("Title", text: $book.title)
    }
}

如果我没办法在当前View创建book对象,它是从外部传进来的呢?

struct BookView: View {
    @Bindable var book: Book  // @ Bindable 修饰,简直就是对象版的@Binding
    var body: some View {
          TextField("Title", text: $book.title)
    }
}

假如有个对象,多个view共用,我不想一个个传递,该怎么办呢?
不妨来一套 @State.environment(...)@ Environment 组合拳

@main
struct BookReaderApp: App {
    @State private var library = Library() // @State 修饰,使其能作为可绑定参数传递

    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library) // 通过注入 .environment() 修改器注入
        }
    }
}

//-----------------

struct LibraryView: View {
    @Environment(Library.self) private var library // 通过 @Environment 修饰符读出
    
    var body: some View {                          
        List(library.books) { book in
            BookView(book: book)       
        }        
    }
}

此时,你想把@Environment变量与控件绑定,发现无法用 $读取(比如$library❌)。
解决方法就是使用@Bindable

You can use the Bindable property wrapper on properties and variables to an Observable object. This includes global variables, properties that exists outside of SwiftUI types, or even local variables.

比如:

struct TitleEditView: View {
    @Environment(Book.self) private var book

    var body: some View {
        @Bindable var book = book
        TextField("Title", text: $book.title)
    }
}

还可以这样用:

struct LibraryView: View {
    @State private var books = [Book(), Book(), Book()]

    var body: some View {
        List(books) { book in
            @Bindable var book = book
            TextField("Title", text: $book.title)
        }
    }
}

参考资料

https://developer.apple.com/forums/thread/732658
https://developer.apple.com/documentation/swiftui/bindable
https://medium.com/@jywvgkchm/transitioning-to-the-new-observable-macro-in-swiftui-8b249673ab1e

标签:Observable,17,Book,ObservableObject,book,var,view,View
From: https://www.cnblogs.com/ZJT7098/p/17780166.html

相关文章

  • VMware Workstation 17.5 Pro Unlocker & OEM BIOS for Windows & Linux
    VMwareWorkstation17.5ProUnlocker&OEMBIOSforWindows&LinuxmacOSUnlocker,支持macOSSonoma请访问原文链接:https://sysin.org/blog/vmware-workstation-17-unlocker/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org桌面HypervisorVMwareWorkstation......
  • VMware Workstation 17.5 Pro for Windows & Linux
    VMwareWorkstation17.5ProforWindows&Linux请访问原文链接:https://sysin.org/blog/vmware-workstation-17/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org桌面HypervisorVMwareWorkstationProVMwareWorkstationPro是行业标准桌面Hypervisor,使用它可......
  • VMware Workstation 17.5 Pro Unlocker & OEM BIOS for Windows
    VMwareWorkstation17.5ProUnlocker&OEMBIOSforWindowsmacOSUnlocker,支持macOSSonoma请访问原文链接:https://sysin.org/blog/vmware-workstation-17-unlocker/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org桌面HypervisorVMwareWorkstationProVMwa......
  • VMware Workstation 17.5 Pro Unlocker & OEM BIOS for Linux
    VMwareWorkstation17.5ProUnlocker&OEMBIOSforLinuxmacOSUnlocker,支持macOSSonoma请访问原文链接:https://sysin.org/blog/vmware-workstation-17-unlocker/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org桌面HypervisorVMwareWorkstationProVMware......
  • 18_JDK8-17新特性
    ......
  • 2023-2024-1 20231417 《计算机基础与程序设计》第4周学习总结
    2023-2024-1 20231417《计算机基础与程序设计》第4周学习总结 作业信息 这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里2023-2024-1计算机基础与程序设计第三周作业这个作业的目标自学教材《计算机科学概论》第4章,第5章 《C......
  • 17-ReentrantLock和java中的aqs
    一、aqsAQS是AbstractQueuedSynchronizer的缩写,是一个用来构建锁和同步器的框架,是线程安全问题(原子性)的一种解决方案通过它可以实现很多不同类型的锁,例如ReentrantLock。主要内容:用state属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控......
  • 17.1 隐藏执行CMD命令
    本章内容涉及使用SocketAPI和CMD命令行工具实现本地CMD命令执行、无管道正向CMD和无管道反向CMD三种功能。执行本地CMD实现使用CreateProcess函数创建一个新的CMD进程,并将标准输入、输出和错误输出重定向到当前进程的标准输入、输出和错误输出。无管道正向CMD和无管道反向CMD使用W......
  • 17.1 隐藏执行CMD命令
    本章内容涉及使用SocketAPI和CMD命令行工具实现本地CMD命令执行、无管道正向CMD和无管道反向CMD三种功能。执行本地CMD实现使用CreateProcess函数创建一个新的CMD进程,并将标准输入、输出和错误输出重定向到当前进程的标准输入、输出和错误输出。无管道正向CMD和无管道反向CMD使用......
  • Odoo16.0 对接17Track
    17TRACK是一家集全球物流快递包裹为一体的查询平台。本文将介绍如何使用odoo与17Track对接,完成物流单号的查询工作。模块安装与配置首先,我们在系统中安装17track模块 安装完成后,我们需要在系统-设置-系统参数中设置从17Track官网申请的AccessToken。 激活承运商......