Search code examples
swiftuikitreactive-programmingrx-swift

RxSwift Subjects to update UI


I have an app that uses the delegate method to communicate controllers with ViewModels. But I would like to start using reactive programming with RxSwift.

The problem I have is that I don't know what subject to use.

The first thing I need is an observable that can notify me when an array of data has changed, but that allows me to add values, modify values, and remove values. And that it can be binded to a tableView.

Is it okay to use BehaviorRelay?

public var array = BehaviorRelay<[Struct]>(value: [])

Example with delegate:

     var posts: [PostStruct] {
            didSet {
    //Call delegate: didUpdatePosts(posts) -> Update TableView
            }
        }

//Also to allow:
posts.append(newPost)
posts.remove(at: index)
posts[index].name = "Hi"

and in the second occasion where I need to use RxSwift is to notify me of changes that have occurred in a property so that I can update the UI.

Example with delegate:

 var post: PostStruct {
        didSet {
//Update UI
//Call delegate: didUpdatePost(post) -> Update UI
        }
    }

The posts are obtained from the database, so it is important to update the table view every time elements are added or deleted.

So... basically what I'm looking for is an observable that notifies me when its value is changed, removed, or added, just like @Published on SwiftUI.

Thanks


Solution

  • From the book "Introduction to Rx":

    Subjects provide a convenient way to poke around Rx, however they are not recommended for day to day use.

    Another useful quote:

    The essence of functional reactive programming is to specify the dynamic behavior of a value completely at the time of declaration. -- Heinrich Apfelmus

    So you want to declare:

    let posts: Observable<[PostStruct]>
    

    In order to specify the dynamic behavior of this value, we first need to know what causes this value to change? It doesn't change for arbitrary reasons, but you didn't really go into detail.

    However, given what you did say:

    • It's clear to me that you need a state machine which means using the scan operator.
    • You mention data coming from a delegate which means you have to convert the delegate to Observables. This article "Convert a Swift Delegate to RxSwift Observables" explains how to do that.

    The only time you should reach for a subject is when you are converting imperative code to declarative (which you should do as soon as possible, the RxCocoa library has done most of that for you already,) or when creating a feedback loop (which is often not needed.)

    For more information:

    Avoid the use of the subject types. Rx is effectively a functional programming paradigm. Using subjects means we are now managing state, which is potentially mutating. Dealing with both mutating state and asynchronous programming at the same time is very hard to get right. Furthermore, many of the operators (extension methods) have been carefully written to ensure that correct and consistent lifetime of subscriptions and sequences is maintained; when you introduce subjects, you can break this.