Reactive Programming and Binding in Swift

Written by dejanatanasov | Published 2017/10/12
Tech Story Tags: ios | swift | ios-app-development | programming | reactive-programming

TLDRvia the TL;DR App

Meet Bond and ReactiveKit

Mobile app consumers have raised the bar for their expectations while scrolling through an app. Nowadays, everyone wants to see smooth transitions, pixel-perfect apps, and fewer steps. Even a small visual distraction can make the user delete your app. In other words, your app has to be perfect.

How do you handle your data changes?

There is also another important thing, and that is how you handle the data changes to the UI. I have met tons of apps with poor handling of data changes. For example, you are pulling to refresh the table view content and suddenly the whole content disappears and reappears after 2–3 seconds. In most cases, you are getting the same results back as before the "pull to refresh", so nothing has really changed. Sounds familiar?

Let's avoid this kind of situations, and handle data changes properly by using bindings and reactive data sources. 👇

Reactive Programming

For those who aren't familiar with the term, reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. For example, all changes to the model will be automatically reflected in the associated view. 📡 If you are interested to find out more about reactive programming click here.

Bind with Bond

Bond is a Swift binding framework that takes binding concepts to a whole new level. It's simple, powerful, type-safe and multi-paradigm - just like Swift. It simplifies state changes by using bindings and reactive data sources.

This library is in my all-time favorites. You can attach it to any component that you like. I will show you how to use Bond with few examples, so you can get the idea of how it's working.

Installation

For the installation, I am using CocoaPods. I highly suggest that you do the same. Just add the below code in your Podfile and run pod install.👇

target 'YOUR_TARGET' do

use_frameworks!

pod 'Bond', '~> 6.4.3'

end

I'm using the latest version of the framework from the day I wrote this post. For version changes, please check here.

Add import Bond to the top of your class so you can use all the Bond methods.

Google Maps SDK for iOS using Swift 4 - The App Space_Many iOS apps use Google Maps. This is a very common feature, so I have decided to prepare an ultimate guide on Google…_theappspace.com

Events

I will start by showing you how to get rid of the annoying process of IBAction and use the simplified approach from Bond instead.

_ = yourButton.reactive.tap.observeNext { print("Button tapped.") }

This will observe your button tap. It listens to touchUpInside because it's the most frequently used event. If you want to handle other events you can use:

yourButton.reactive.controlEvents(.touchUpInside).observeNext { e inprint("Button tapped.")}

Another example would be observing the text changes in a UITextField. Knowing that there is no native approach to this situation, Bond provides us with a simple solution.

_ = yourTextField.reactive.text.observeNext { text inprint(text!)}

Now, let me show you a simple binding of the typed text into a UILabel. The text will get transformed by using the .map closure and propagated to the label. $0 is the typed string, so you can add any string transformation that you need.

yourTextField.reactive.text.map{ $0?.capitalized }.bind(to: yourLabel)

Or, you can use the above example but provide a condition instead. Let's say you need to change the button enabled state as someone types in the text field.

txtField.reactive.text.map { $0!.characters.count != 0 }.bind(to: yourButton.reactive.isEnabled)

Observable

Observables are signals and a typealias for the ReactiveKit Property type. Whenever the state of the Observable changes, an observer will be notified.

let animal = Observable("Dog")

animal.observeNext { value inprint("Hi \(value)!")}

If you can see from the example, whenever the animal observable changes its value an observer will be triggered. To change the value just call animal.value="Cat". To bind an Observable with a UI component just use animal.bind(to: yourLabel).

Bond also supports two-way binding by using bidirectionalBind. It means that if the view value changes, it will update the Observable value and vice versa.

animal.bidirectionalBind(to: animalTextField.reactive.text)

Instagram API Authentication using Swift - The App Space_This tutorial is about Instagram API Authentication using Swift and will teach you how to retrieve the ACCESS_TOKEN…_theappspace.com

Reactive Data Sources

By using reactive data sources, it allows us to easily observe changes in a table or collection view. That means whenever the array changes, the data source methods will update automatically. No need of adding reloadData() on each array change, and it will update only the changes that were made. 🤘🤘🤘

We need to use MutableObservableArray or ObservableArray that will observe for changes and pass the changes automatically to the data source methods.

let array = MutableObservableArray([“John”,”Michael”,”Steven”])

I will now present you how easy and short it is to implement the data source of a table view. You don't need to connect the UITableViewDataSource with the table view, as Bond handles that for us.

The mandatory numberOfRowsInSection()and cellForRowAtIndexPath() , are "packed" under the array bind() method. In the closure, you can add your own cell logic. See the example below. 👇

array.bind(to: tableView, animated: true) { dataSource, indexPath, tableView in

let cell = UITableViewCell(style: .subtitle, reuseIdentifier: “cell”)

cell.textLabel?.text = dataSource[indexPath.row]

return cell

}

Now, let's say that the array needs to be updated. At this point, we need to only focus on the array, and forget about the table view and whether it's going to update or not.

Here are some methods that you can use to make changes to the array.

array.append("Brad") /* appends array with a new object */

array.insert("Brad", at: 2) /* inserts new object at the given index */

array.replace(with: [“John”,"Brad",”Michael”,”Steven”], performDiff: true) /* replaces the array but updates only rows that weren't present in the previous array (in our case index 1) */

array.moveItem(from: 1, to: 2) /* items in array will change places */

array.remove(at: 2) /* removes an item from the array */

array[1] = "David" /* replaces the value at the given index */

By using these methods properly, we provide the best user experience possible. The data will be updated, and the user won't get distracted in any way.

I have presented just a few of the many features that Bond offers. Binding and the reactive paradigm can bring your app to the next level, so I would strongly suggest using this approach. If you want to spread the message, please don't forget to 👏 or share this story.

Thank you for your attention! 🚀

Check out my latest project:

‎VIP Sports Bet Tips & Scores on the App Store_This app is only available on the App Store for iOS devices. Increase your profits by following our professional BET…_apple.co

Read more of my writing on Medium:

Introducing Clean Swift Architecture (VIP)_Forget MVC, now!_hackernoon.com

Your ultimate guide to the Google Maps SDK on iOS, using Swift 4_Many iOS apps use Google Maps. This is a very common feature, so I have decided to prepare an ultimate guide on the…_medium.freecodecamp.org

SWIFT — Custom UIView with XIB file_Custom UIView with XIB file is a very common practice in iOS Development. Custom UIView classes don’t contain XIB files…_medium.com

How to add Spotlight support to your iOS app_A Swift tutorial that will make your app available in Spotlight search_hackernoon.com

Core Data Relationships_Understanding One-to-One and One-To-Many relationships_hackernoon.com

Understanding Auto Layout in Xcode 9_All you need to know about Auto Layout_hackernoon.com

Subscribe to my Newsletter:


Published by HackerNoon on 2017/10/12