My name is Bond…SwiftBond

Manually wiring up UI Code is tedious and requires a lot of work and usually does not behave the way you would like. But do we really need to do this manually every time? SwiftBond is a binding framework that takes binding concepts to a whole new level. It is simple, powerful, type-safe and multi-paradigm - just like Swift. Craig has been using SwiftBond for over a year and covers how easy it is to get started and use in a project. Craig shows how during a live NFL Patriots game he uses SwiftBond to update all game data in real time for users, as well as other examples of how you can use Bond to simplify your code.

Introduction (00:00)

My name is Craig Clayton. I am from Florida, live in Tampa, and I work for a company called Adept Mobile; we build iOS and Android apps for NFL and NBA teams like the 49ers, the Patriots, and the Celtics. I love sports. We also do UFC Fans, which is great when you get to watch a fight, and everyone is excited. We get to watch it for free, to just sit there and test, and we always find reasons to test. I also run the Suncoast iOS meetup group in Florida, we have about 600 members, it may be more now; it is great to be able to help. I have been giving presentations for three years, and for the past year, I focused on doing only hands-on workshops. Just so that I can give more to the community, and get more people involved in Swift. Swift has taken storm in Florida, and everywhere, but it is great to be able to help people; especially minorities who are getting into creating apps, and kids who want to make games. It is a wonderful thing. Next week I am also giving an all-day workshop at Forward Swift about creating a game: Soccer Pong.

Now, the reason why we are here: SwiftBond. Very few people here have heard of SwiftBond, and that is why I am giving this talk.

What is SwiftBond / ReactiveKit? (03:06)

SwiftBond is a Swift binding framework that I have been using since 2015 for version two: it is great with dealing with UI. I can bind data to a label, or to a button, and then all I have to do is update a value and everything works.

SwiftBond has changed its name to ReactiveKit. All of my production code is still using SwiftBond, so that’s why I’m going to be talking about it. I have moved a test project over to ReactiveKit, and it probably only took me 30 minutes.

The first time I saw ReactiveCocoa, I had a really bad impression. What I liked about SwiftBond when I first saw it was, I could drop it into a project, and within 10 minutes it starts working. Now, ReactiveCocoa is also great, I use it for API requests and getting feeds. But for UI purposes SwiftBond is my choice. I have a coworker who loves ReactiveCocoa. I could tell him, “I will give you $1,000,000 to switch,” and he will say no. He loves ReactiveCocoa, and you can use both, but I like Swift and ReactiveKit, and I will show you the reasons why.

In my slide, you can see a simple example of how SwiftBond works. Everything is “binded” through Bond, and it’s either a bind or an observe. It’s really simple, and I’ll show you how simple it is because all the code will fit on my slide. That should give you a good reason for why you should want to use it.

UILabel (06:22)

Let’s start with a UILabel. ReactiveCocoa uses a label and a text, that is usually their demo, then you have to spend hours trying to figure out how to do other stuff.

@IBOutlet var lblAway: UILabel!
var awayScore = Property<String>(0)
awayScore.bindTo(lblAway)

So here, all I do is:

  • Create an outlet.
  • Create a string and make it a property, set a default value to it.
  • Bind it.

That is all I have to do. With this bit of code, you can download, put it on Playground or Xcode, and you are already up and running and ready to go.

UIButton (07:09)

btnReset.rTap.observeNext { [weak self] _ in
  guard let weakSelf = self else { return }

  weakSelf.homeScoreValue = 0
  weakSelf.awayScoreValue = 0
  weakSelf.awayScore.value = "0"
  weakSelf.homeScore.value = "0"

}.disposeIn(rBag)

I typically do not use IBActions, but instead I use Reactive to do all of my actions. I am going to create an observe on the rTap. For buttons, there are multiple things that you can observe, and rTap is one of them. I create an observe, guard it with [weak self], and then I reference values. .value is the value of a string that I change, and anytime I change it, anything that is observing it or bound to it, will react to Reactive. That is all I have to do. I do not have to do anything else other than do .value = "something".

In my demo on slide 8, I have a reset button at the bottom; it is changing all of the labels and resetting everything back to zero: that is all it is doing, everything works, and that is all the code I wrote to do that. You also have .disposeIn at the end of the code snippet. That is something new with ReactiveKit; it wasn’t in SwiftBond. That is garbage collection. Once you get out of the view controller, you are giving this to garbage collection, and you are letting it go. It is simple; you just drop it at the end. If you do not add it, it is going to complain that you are not setting it to a variable. It wants you to use this or use a variable to use this particular observe. You will notice that on all of my examples, I have disposeIn(rBag), and rBag comes with all UI or NSObjects free with ReactiveKit.

UIBarButtonItem (09:06)

barBtnCamera.rTap.observeNext { [weak self] _ in
  guard let weakSelf = self else { return }
   weakSelf.lblDisplay.rText.value = "Camera Tapped”
}.disposeIn(rBag)

I have this exact code rTap.observeNext. I check for weakSelf, set the label, the rText.value and change “Camera Tapped”. That is it. Again, I add disposeIn and use garbage collection.

UISegmentedControl (09:38)

segmentControl.rSelectedSegmentIndex.skip(1).observeNext { ... in
  guard let weakSelf = self else { return }

  if value == 0 {
    weakSelf.lblDisplay.rText.value = "Players Segment selected" }
  else {
    weakSelf.lblDisplay.rText.value = "Coaches Segment selected" }

}.disposeIn(rBag)

Here, I am accessing the selected segment index, and I am using a skip. That is saying, “the first time something comes through just ignore it; after that, I want to know what happens.” If you do not use it, it will run; if you do not care about that, you do not have to include it. That is another new thing in ReactiveKit versus SwiftBond. Before, you did not necessarily have to include that; it was only when a user interacted with something that it would call. Now it calls from the beginning. Again, we use weakSelf and check to see if the value is zero or if the value is one, in this case, because I only have two segments. And again, garbage collection.

UISwitch (10:35)

switchReactive.rOn.skip(1).observeNext {
                          [weak self] value in

  guard let weakSelf = self else { return }
  weakSelf.lblDisplay.rText.value = “\(value)"

}.disposeIn(rBag)

Once again: simple. I check for the “on” state of this, and it is going to give me back a true or a false. In this example, I just throw this in a text value, but in your UI you can do anything you want. Update your model, change the values, and then everything gets updated.

All the code is available to you on my GitHub. I am not hiding anything: everything you see is showing you how simple it is to get involved with doing binding with your UI versus having to do protocols or delegates.

UITableView (11:28)

tableView.rDataSource.forwardTo = self

data.bindTo(tableView) {
  [weak self] indexPath, dataSource, collectionView in
    guard let weakSelf = self else { return UITableViewCell() }
    let cell = weakSelf.tableView.dequeueReusableCellWithIdentifier
                    (weakSelf.textCellIdentifier, forIndexPath: indexPath)
    let row = indexPath.row
    cell.textLabel?.text = weakSelf.data[row]

    return cell
}

Another wonderful thing about SwiftBond (aka ReactiveKit) is that I can bind to table views and collection views. This is something that ReactiveCocoa is starting to do, but this has been out, and I’ve been doing it for over a year. The basic concept is you have an array - whenever you put something in your array, your table view updates. I do not have to worry about data source, delegate, or listening for data source, and my code is one method. You also have a tap and a selected state.

You are going to create a rDataSource.forwardTo and set it to self. Then you are going to bind your data (whatever your array is that you have), bind that to your table, and guarding in case something comes through, so you send it an empty cell. If you have done any table views, this code always looks the same. I wrote this line of code, and now all I have to do is insert or remove things from my array. I have this ability to make my app more powerful.

I use this in my apps. For NFL we have play-by-play data that comes through we do not want the user to keep pulling and refreshing. We do some similar stuff with UFC Fans, where we have live fight-by-fight data, and we do not want the user to have to pull and refresh every single time they want an update. We hit the feed, update our model and everything updates.

Real-world Examples (13:22)

Okay, so you might be asking yourself, where are the real use cases? The 49ers app you can see on slide 47 is running the HUD: that is all through SwiftBond. I set a timer for when the game is live to hit the feeds every 10/20 seconds. Anytime our feed adds a new play or there are any changes, this will update automatically. All I have to do is hit my feed, and it updates.

As another example, I like shoes, and you can see on slide 38 they are not high heels, they’re Jordans. This app was great to use as an example because it shows the power of SwiftBond in one view. I can add things to the cart and when I add things to my array, the other side updates; both sides are collection views.

One more example of how SwiftBond works is play-by-play data: when the user goes in and watches the game, everything is being updated: the score, the time, the possessions, the current and the previous plays. In the newer version, all the plays animate in; it is not an abrupt adding of an item into the array.

These are a few things that I have used SwiftBond / ReactiveKit; I love using it. I enjoy being able to open my app and immediately bind all my UI data to it. I highly recommend it; if you are in doubt take 10 minutes, download it, play with it, and I promise you within maybe 15 or 20 minutes you are going to be, “I like it.”

Q & A (17:00)

Q: Where do you typically store these properties? Are you storing them in the view controller, or do you have some other pattern you are using? Craig: I am probably one of the few people that really likes VIPER. All of my app structures since 49ers, I think there are five sports apps that I have done recently, they are all structured on VIPER. Everything I put is in the API data manager and gets passed on, or I have a client, and then I just pass those through parameters. I just bind to the data and everything else updates, which is great because the HUD that you saw in the initial list view and the detail, they all work off the same model. All the data are updating in one place at one time.

Q: How did you update the timer in that screen of the game? I am curious. Craig: The timer that shows the players coming through, I had a static array that updated every five seconds I ran a timer. In the app for the actual feeds, I set a timer for 20 seconds, and every 20 seconds it hits the feed again, updates my model, and anything that is listening to that particular data updates my UI. All I have to do is focus on updating my model, and everything else is done.

Q: The first question, you had a screen with the time of the game playing that updated every second. Craig: The time is just a string in our feed. When the feed updates, it just changes the string, so it looks it is actually counting down or using a timer, but it is just an updated label that has a string value.

Q: What is the debugging experience like, and what do you feel are the main benefits to this over notifications in KVO, is it just that it is more expressive and compact, or have you discovered other benefits besides expressivity? Craig: When I brought this to WWDC to debug the Colts app, they could not find anything, which was good. I have not had many issues using it. The guy who does ReactiveKit is really good about updating it. It is not a huge community. Ray Wenderlich has posted, I think, last year maybe about SwiftBond but debugging wise I have never really had much of an issue using it.

Notifications in KVO, I have always been taught that those are bad to use, just depending on what you are doing. I have always stayed away from using notifications unless I absolutely had to. What I like about ReactiveKit is all of the stuff that you see, the UI, I only showed four, but any user interface is used with SwiftBond or ReactiveKit, and everything is an extension. It is just Swift code; it is not a massive library. I could write it myself, and he is using KVO, but he is simplifying all of his stuff for me and making it easy for me to just drop it into my project and go.

Q: Is it easy to override the binding? If you have, for example, a UILabel bound to an integer, and you want to put a string in there? Or you have a score, and it is e.g. one, two, three, but you start the game over, and you want to say, “not available”, or “nothing” or “X”, is that easy to do Craig: Swift will not let you do that in general. In our case, I believe all the scores are integers, and I just convert them to strings after. I put it into quotes in slash, and then just make it a string.

Craig: Tweet me if you have any questions. I will be more than happy to jump on Twitter or jump on Hangouts and show you some stuff if you still are lost but I think with the project and the slides you will be able to do what you want. Collection views and table views look exactly the same, just swap out collection views for table views and you pretty much have the same code.

Resources


Craig Clayton

Craig Clayton

Craig Clayton is a Sr. iOS Engineer at Adept Mobile, which specializes in building mobile experiences primarily for NBA & NFL teams. Craig also volunteers as the organizer of the Suncoast iOS meetup group in the Tampa/St. Petersburg area, and prepares presentations and hands-on talks for the community. On top of all that, Craig is also the owner of Cocoa Academy – launching in Jan 2017, Cocoa Academy specializes in iOS video courses.