» » Why Reactive Programming in Swift?

Why Reactive Programming in Swift?

Improving code readability

Everyone knows about the nightmarish closures in Swift. Due to the nature of mobile development, asynchronous processes must be called on time. Previously, this was done using closures. Some of you may still use closures for this, and that's fine.

But one day you will run into nested closures. And the nightmare will begin. Reading and editing nested closures is painful. Everyone understands this.

Why Reactive Programming in Swift?

And how does reactive programming in Swift help reduce this pain?

You can chain observables with the map, flatMap and flatMapLatest functions. This way, you can process requests simultaneously without having to bother reading nested closures.

Also, the merge, combine, and zip functions make it possible to execute multiple queries in a more manageable and readable way. Here is a quote about the importance of good readability:

Of course, the ratio of time spent reading code to time spent writing code is about 10 to 1. We are constantly re-reading old code as part of the process of writing new code. Therefore, making the code easier to understand also makes it easier to write it.

Robert S. Martin, "Clean Code: Creation, Analysis, and Refactoring"
, Position of the author


Therefore, it is very useful to spend time on making your code more understandable and readable.

This does not mean that you should completely stop using closures. However, by using closures along with the reactive library of your choice, you can make your code more readable.

Help with event handling


In a common iOS development scenario, you need to respond to events from different parts of the application. For example, someone has changed their name in one controller and needs to update it in another.

There are several scenarios for such cases: delegates, notifications, and key-value pairs. Each of them works well. But the reactive approach has a lot to offer.

First, reactive programming can make these scenarios easier to work with. All you need to do is create an observer or subject and subscribe to it. Then, every time an observer spawns an object, all subscribers will know about it.

You can use this syntax:

class MyController {
  let subject:PublishSubject = PublishSubject()

  func doSomething () {
    let object = MyObject()
    self.subject.onNext(object)
  }
}

class OtherController {
  func doSomething () {
    let controller = MyController()
    controller.subject.subscribe( (myObject) in {
      // do something with myObject
    })
  }
}


See, it's quite simple. This doesn't require a lot of code. As I said earlier, one of the hallmarks of a great codebase is that anyone can understand it.

You can subscribe to subject from the first controller anywhere in the program. And then use myObject for your purposes. For example, skip the first two objects. You can use the skip function for this. And like I said, you can combine observables with the merge and zip functions.

If you need hooking, you can use the protocol and access the subject through it. For example:

protocol MyProtocol {
  var subject:PublishSubject { get }
}

class MyController: MyProtocol {
  let subject:PublishSubject = PublishSubject()

  func doSomething () {
    let object = MyObject()
    self.subject.onNext(object)
  }
}

class OtherController {
  func doSomething () {
    let controller = MyController()
    controller.subject.subscribe( (myObject) in {
      // do something with myObject
    })
  }
}


Make code more modular


One of my favorite things about reactive programming is passing observables as variables. For example, you can pass a network request to another object and execute it when needed. This allows you to make the code more readable and modular.

Let's say you have controllers that require a particular type of observer. You can use them with any network requests whose observers produce objects of the desired type.

I always use this when I need reusable controllers to display data to the user. Let's take an application similar to Instagram, where there is a post object, and a screen where these posts are displayed. You need to display posts of one or another user on the same screen. Since this is most likely done with network requests, you can create the request as an observable and pass it to the controller. The controller will do the rest.

This is a code snippet illustrating my main idea:

class Networking {
  static func getPostByUserWithId (_ userId: string) -> Observable<[Post]> {
      let request = NetworkingLibrary.request(.GET, "http://someapiurl.com", parameters: nil)
            .response(completionHandler:  { request, response, data, error in
                if let error = error {
                    observer.onError(error)
                } else {
                    let posts = convertDataToPosts(data)
                    observer.onNext(posts)
                    observer.onCompleted()
                }
            });
  }
}

class Controller {
  func doSomething () {
    let postsObserver = Networking.getPostByUserWithId("the_users_id")
    let displayPostsController = DisplayPostsController(postsObserver)
  }
}

class DisplayPostsController {
  init (postsObserver: Observable<[Post]>) {
    // subscribing and displaying query results
  }
}


So the advantage here is modularity and versatility. This single controller can be reused any time you need to display a list of messages. And all you have to do is pass an observer to it. The controller will do the rest.

In addition to the above features, reactive programming in Swift:

- allows you to effectively debug code;
- greatly reduces the number of lines of code;
- when using libraries such as RxSwift or RxCocoa , it makes it possible to use traits for a better understanding of the code;
- well suited for MVVM architecture;
- allows you to execute chains of queries with a couple of lines of code.

Related Articles

Add Your Comment

reload, if the code cannot be seen

All comments will be moderated before being published.