SwiftUI Apple out of the box MVVM ViewModel

What is a ViewModal

A ViewModal is an intermediate layer between a View and data. The ViewModel is the layer between the view and the data. Viewmodels typically use Service Objects to fetch data, format it, and provide formatted data to the View.

When did Apple start pushing MVVM

When Apple moved the ObservableObject protocol to the Combine framework, Apple began to promote the MVVM pattern. Let’s look at the ObservableObject protocol to see what’s going on.

/// 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 }
}
Copy the code

The ObservableObject protocol has a unique requirement, that is, the publisher issued before the object changes. Let’s write the first ViewModel that conforms to the ObservableObject protocol.

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
    }
}
Copy the code

Here, we have the ViewModel to get posts, store them in variables, and notify them through the objectWillChange publisher. Let’s look at an example ViewController that uses this ViewModel.

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)
        }
    }
}
Copy the code

As you saw in the example above, we have PostsViewController, which starts observing changes in the ViewModel and then asks the ViewModel to extract data. Once the ViewModel extracts the data, it emits, and the ViewController calls the renderPosts function, which displays the downloaded posts.

Published property wrapper

We can go further by using the @Published property wrapper. The @Published Property wrapper allows us to wrap publishers around any property and publish the current value whenever the property changes.

final class PostsViewModel: ObservableObject {
    @Published private(set) var posts: [Post] = []

    func fetch() {
        // fetch posts and assign them to `posts` variable
    }
}
Copy the code

As you can see in the example above, we don’t need to manually send values to the objectWillChange publisher; that’s all the Swift compiler composition does. And we can keep the same implementation of PostsViewController.

As mentioned earlier, the @Published property wrapper wraps our properties with the publisher. Let’s see how we can use it in PostsViewController, okay

final class PostsViewController: UIViewController {
    let viewModel: PostsViewModel

    override func viewDidLoad() {
        super.viewDidLoad()
        bindViewModel()
        viewModel.fetch()
    }

    private func bindViewModel() {
        viewModel.$posts.sink { [weak self] posts inself? .renderPosts(posts) } } }Copy the code

So here, we have a refactored version of PostsViewController. Take a look at how we changed the bindViewModel function. It now subscribes to $posts, and it allows us to update the view only when certain properties change. As long as your ViewModel has more and more fields that affect the view, you’ll see immediate benefits.

conclusion

We can easily implement the same logic using RxSwift, ReactiveSwift, or any other reactive framework such as Bond. But I think MVVM will become the default choice for architected iOS applications. At least until now, when Apple provided us with all the necessary tools right out of the box.

The article source

Swiftwithmajid.com/2020/02/05/…

More SwiftUI tutorials and code focus columns

QQ:3365059189 SwiftUI Technical exchange QQ group :518696470

  • Please pay attention to my column icloudend SwiftUI tutorial and the source www.jianshu.com/c/7b3e3b671…