RxSwift and Memory

Tom Burns asked a good question about TableView bindings outliving the view controller. As he said:

I’m asking because I noticed that some of my tableview bindings were outliving the view controller being popped back off the stack and it seemed like unnecessary work was being done…

kzaher of the RxSwift Slack community pointed out the following code as being the culprit:

Tom fixed the code to use an “[unowned self]” before the newObjects. Such as:

Although such memory situations aren’t limited to RxSwift, using RxSwift might encourage such situations to come up more often. It something to watch out for.

Regardless, this is something we all can run into from time to time. I feel fortunate enough to have caught the conversation in the RxSwift Slack community and am grateful to Tom for asking.

Learning RxSwift

Although ReactiveCocoa looked promising, it had a few things that are not yet there. These are outlined in an earlier article, ReactiveCocoa and MVVM Initial Experience. So, it was time to explore RxSwift.

I started with reading the concepts in the README. It was pretty straight forward. My next move was to find an example which is like the ReactiveCocoa oriented ReactiveTwitterSearch example that I loved so much. Where to begin? Good thing I discovered the RxSwift slack community.

Having an active slack community is a huge win! With the help of Carlos García in slack, I found GitHubSignup in the RxExample examples. This was definitely what I was looking for.

For fun, I created a small demo app which explored the bindings. I decided to see what was there for a UIPickerView and UITextView.

Compared to ReactiveCocoa, the RxSwift repo comes with extensions to some of the UIKit components. These are known as RxCocoa extensions. RxCocoa is located alongside the RxSwift code in the GitHub repository. However, if you are using CocoaPods like I am, RxSwift and RxCocoa are two separate pods.

After much searching, I discovered there is no extension made for the UIPickerView. So, I just made a PickerViewAdapter which contains a selectedPerson RxSwift Variable and PickingPersonViewModel. The adapter handles the UIPickerViewDelegate and UIPickerViewDataSource while calling through to the PickingPersonViewModel. The adapter is used by the View Controller.

With the UITextView, I had much better luck. With a simple binding, I was able to hook up a notes UITextView up with a specific note in the NotesViewModel. Changes to the UITextView would be reflected in the note. Pretty neat! Code is here:

_ = notesTextView.rx_text.subscribeNext { someText in

// Changes to notesTextView’s text triggers this block.

self.notesViewModel.currentNote().value.text = someText

}

How do extensions like rx_text work? I looked at the simplest example, the RxSwift UILabel extension. AnyObserver has an observer which is an event handler. As can be seen in the code, the UILabel extension with rx_text is an adapter that handles String events.

Although it’s currently Beta, there’s a sense that RxSwift will be out of beta soon. This is based on a Github request for it to be released as 2.0.0.

Based upon my observations and discussing it with some smart people at CARFAX I know, it looks like RxSwift is pretty solid. If you are interested in supporting MVVM in a Functional Reactive programming style, I recommend you check it out!

ReactiveCocoa and MVVM Initial Experience

The vision of Functional Reactive Programming (FRP) and specifically ReactiveCococa (RAC) 4.0 alpha are both impressive. FRP via RAC and Swift feels right. As mentioned in my previous article, RAC 4.0 is useable. Its core concepts are quite solid. Yet, one has to really want to dive in and be willing to offset any UIKit shortcomings. That’s fair since RAC 4.0 is alpha.

Where ReactiveCocoa needs more help:

  • There is a need for the ReactiveCocoa CocoaPods spec to be updated
  • There is a need for more UIKit extensions

Need for Updated ReactiveCocoa CocoaPods spec

That’s probably easy for one to do since it’s an update to an existing pod spec. If one doesn’t have time or want to, one can use Carthage as mentioned in my previous article, Swift 2 ReactiveCocoa MVVM Quest.

More UIKit Extensions

Based on a post here by Neil Pankey (a collaborator on ReactiveCocoa), Rex is a ReactiveCocoa Extensions project that eventually will get merged into ReactiveCocoa. As Neil mentions:

It’s not there yet, because “..haven’t found the time to port them, flush out the missing properties, add documentation, etc”

Although it has some extensions, more are needed. I immediately came up for the need for an extension that would let me capture text in a UITextField. Digging deeper I see in a somewhat older post, that there are many extensions that need to be ported over to Swift. Looking at Rex UIKit specific code myself, I think that’s still the case. If the community rallies around making more UIKit Extensions, it would help everyone.

To address what I needed now, I used a fork of ReactiveTwitterSearch originally made by Colin Eberhardt, and grabbed the UIKitExtensions code and a couple other items. Doing that, I was able to bind the text put into a text field straight into a View Model like so:

        loginViewModel.username <~ usernameTextField.rac_text

That line of code is quite similar to the awesome but dated article RAC 3 Properties section of MVVM with ReactiveCocoa 3.0.

So, that is neat and powerful since with some easy to read binding/configuration one is making it much easier to do MVVM. As long as you don’t mind, piecing things together and absorbing the learning curve, this power is yours for the taking now.

Swift 2 ReactiveCocoa MVVM Quest

The Quest

For a software developer (especially at CARFAX), the quest for cleaner code is worthy and eternal. In Swift and Objective-C, two main battlefields where clean code is threatened are View Controllers and client network code. View Controllers get big and client network code suffers from the Pyramid of Doom. The Pyramid of Doom is where there are many nested statements as shown in this Traditional asynchronous code slide. Following the advice of a smart friend named Mike Groner, I looked into ReactiveCocoa (RAC) and revisited MVVM.

Since we have looked at MVVM before and MVVM’s roots go way back to the Presentation Model via Martin Fowler, its concepts are not foreign. It’s true that one does not have to use RAC to do MVVM. As Natasha The Robot showed in her Swift Summit presentation and related Protocol-Oriented MVVM (POMVVM) article, one can manually follow the discipline of doing POMVVM without a framework. So, that’s great. One concern is that it requires the team to relentlessly apply discipline to do POMVVM well.

Shifting our attention to the Pyramid of Doom, how can RAC and Functional Reactive Programming in general help? To answer that question, I checked out Javier Soto‘s Back to the Futures Swift Summit presentation. It was eye opening. It discussed how we typically handle asynchronous callbacks (thus the Pyramid of Doom), error handling, and the concept of Futures as a way of getting rid of “…all the noise related to the asynchrony itself.” Easier to write, read and maintain code through Futures / Promises or better yet Signals sounds good! At the end of the talk, he also recommended ReactiveCocoa aka RAC.

So, What About ReactiveCocoa (RAC)?

OK. The message is loud and clear: Check out RAC! Natasha-The-Robot, guided me to Ash Furrow. Ash helpfully shared Functional Reactive Awesomeness With Swift So, RAC is impressive and RAC may even help one do MVVM. Which version of RAC should I investigate?

For an upcoming project, using Swift 2.1 is a no brainer. Can RAC or something similar be used in a Swift 2.1 project?  NachoSoto comes to the rescue on Twitter and Stackoverflow:  How to Add Production Ready ReactiveCocoa … Into Swift 2 iOS. So, the answer is yes!

Getting ReactiveCocoa 4.0

Being more than ready to dive into ReactiveCocoa 4.0, the question was now “how to get it?” I tried using CocoaPods, but the unofficial podspecs were out of date. it seems like a good answer is using Carthage with a Cartfile of:

github "ReactiveCocoa/ReactiveCocoa" "v4.0.0-alpha.3"

Since I have been a CocoaPods user, it didn’t immediately occur to me to copy the frameworks as per the RAC README page:

On the “General” tab of your application target’s settings, add ReactiveCocoa.framework and Result.framework to the “Embedded Binaries” section.

Success!

RAC and MVVM?

Could RAC or something like it also help with MVVM? Both my friend and Ash Furrow’s presentation above suggested that it could do so beautifully. Searching the web for the most recent ReactiveCocoa Swift examples, I found MVVM With ReactiveCocoa 3.0 by Colin Eberhart and Migrating to Swift 2 and ReactiveCocoa 4 by Martin Richter. So, it certainly seems so.

With ReactiveCocoa 4.0 and examples at hand, the journey has just begun and the quest for clean and well crafted code continues!