• SwiftUI


    SwiftUI - MVVM之ViewModel

    什么是ViewModal

    ViewModal是View和数据的中间层。ViewModel是视图和数据之间的一层。 ViewModel通常使用service objects来获取数据,对其进行格式化后向View提供格式化的数据。

    苹果什么时候开始推动MVVM

    当苹果将ObservableObject协议移至Combine框架时,苹果公司开始推广MVVM模式。让我们看一下ObservableObject协议,以了解发生了什么。

    /// A type of object with a publisher that emits before the object has changed.
    public protocol ObservableObject : AnyObject {
    
        /// The type of publisher that emits before the object has changed.
        associatedtype ObjectWillChangePublisher : Publisher = ObservableObjectPublisher where Self.ObjectWillChangePublisher.Failure == Never
    
        /// A publisher that emits before the object has changed.
        var objectWillChange: Self.ObjectWillChangePublisher { get }
    }
    

    ObservableObject协议具有唯一的要求,即在对象更改之前发出的发布者。让我们编写第一个符合ObservableObject协议的ViewModel。

    final class PostsViewModel: ObservableObject {
        let objectWillChange = PassthroughSubject<Void, Never>()
    
        private (set) var posts: [Post] = []
    
        func fetch() {
            // fetch posts
            objectWillChange.send()
            // assign new data to the posts variable
        }
    }
    

    在这里,我们有ViewModel来获取帖子,将它们存储在变量中,并通过objectWillChange发布者发出通知。让我们看一下使用此ViewModel的示例ViewController。

    final class PostsViewController: UIViewController {
        let viewModel: PostsViewModel
    
        override func viewDidLoad() {
            super.viewDidLoad()
            bindViewModel()
            viewModel.fetch()
        }
    
        private func bindViewModel() {
            viewModel.objectWillChange.sink { [weak self] in
                guard let self = self else {
                    return
                }
                self.renderPosts(self.viewModel.posts)
            }
        }
    }
    

    如您在上面的示例中看到的,我们有PostsViewController,它开始观察ViewModel中的更改,然后要求ViewModel提取数据。一旦ViewModel提取数据,它就会发出,并且ViewController调用renderPosts函数,该函数显示下载的帖子。

    Published property wrapper

    我们可以使用@Published属性包装器进行进一步操作。 @Published属性包装器允许我们将发布者包装任何属性,只要属性更改,发布者就会发出当前值。

    final class PostsViewModel: ObservableObject {
        @Published private(set) var posts: [Post] = []
    
        func fetch() {
            // fetch posts and assign them to `posts` variable
        }
    }
    

    正如您在上面的示例中看到的那样,我们不需要手动将值发送给objectWillChange发布者,这是Swift编译器合成的所有工作。并且我们可以保持PostsViewController的相同实现。

    如前所述,@ Published属性包装器将我们的属性与发布者包装在一起。让我们看看如何在PostsViewController中使用它

    final class PostsViewController: UIViewController {
        let viewModel: PostsViewModel
    
        override func viewDidLoad() {
            super.viewDidLoad()
            bindViewModel()
            viewModel.fetch()
        }
    
        private func bindViewModel() {
            viewModel.$posts.sink { [weak self] posts in
                self?.renderPosts(posts)
            }
        }
    }
    

    在这里,我们有一个PostsViewController的重构版本。请看一下我们如何更改bindViewModel函数。它现在订阅$ posts,并且仅当特定属性更改时,它才允许我们更新视图

  • 相关阅读:
    postman接口测试01_下载安装
    Jenkins持续集成_05_参数化构建
    IntelliJ 中设置与Eclipse中 Ctrl+1 功能类似的快捷键
    JAVA 内部类
    Adobe Air 现在可支持X86的移动设备
    开发一些自动编写代码的工具可以增加效率吗?
    制作 Flex 悬停提示帮助文档(转)
    没什么好说的
    JDK,Tomcat,Maven,Mysql环境变量配置
    神器三、Android端神器东皇钟:天界之门
  • 原文地址:https://www.cnblogs.com/liuxiaokun/p/12684399.html
Copyright © 2020-2023  润新知