Skip to main content

A ReactiveCocoa Core Data App Using Singleton Pattern

Front-end Development
Back-end Development
Mobile Development

Disclaimer: The way I describe things below is simply one way to do things.  I am not saying this is the best way.  It is simply the way that I, at this particular point in time, am putting together iOS applications using ReactiveCocoa and Core Data.

My approach is a little bit Singleton based and a little bit MVVM pattern based.  The size and complexity of a project determines how much I use one over the other.  The main principles I like in these patterns are 

  • Having one Data Management Class that all views can reliable goto for the state of the app. (uh oh, I said state, FRP is about removing state, which is a great principle, but I've not been able to completely eliminate state, at least not practically)
  • Removing business logic from View Controllers.  The MVVM pattern suggests that we create a view model, and simply bind the values of a view controller to it's view model, leaving just the interactive stuff for the view controller to worry about.

Most Core Data based apps will have some requirement of pulling data from a remote service of some kind.  This means the app will get the data is uses from one of two different locations. Core Data, or the Web Service.  For testability, it's nice for the app to not care too much about where the data is coming from.  So adding some abstraction is a great idea.  I like to have all Data for the app originate in a class called DataManager.  The the DataManager will decide where to pull the data from based on a number of conditions.  Since there are two places data can come from we will create two more classes that will sit behind the DataManager class and each handle one data source.  I like to call the class that handles Core Data fetching the PersistenceClient, and the one that pulls from the remote service, the ServiceClient.  The DataManager will be the ONLY one who talks to these two classes, and the rest of the app ONLY talks to the DataManager for it's data.  

I have the arrows pointing up the chain in the diagram, though from a reactive standpoint they should be going the other way.  Because signals from the Clients and DataManager are sending data to the rest of our app.  We do have to make calls to get the producers that create these signals.  So while in theory, data is flowing "down", we need to subscribe to this data which is more upward.

Example Scenario

Say our app is concerned with knowing the network status at any given point.  The DataManager can have a signal that sends values to it's observers anytime this status changes.  So anywhere in the app, we can subscribe to this signal and make the appropriate changes to the UI, etc.  I like to leverage the "library" Reachability from Ashley Mills.  Our method in the DataManager may look something like this.

First create a signal (not a SignalProducer) on the DataManager that we will send values on when things change.


  let (reachabilitySignal, reachabilitySink) = Signal<Reachability.NetworkStatus, NoError>.pipe()

Then, somewhere in the initialization of our DataManager class we can have a chuck of code that forwards information into the reachability pipe.

do {
  let reachabilityNotifier = { (rb: Reachability) in
    self.reachabilitySink.sendNext(rb.currentReachabilityStatus)
  }
  reachability = try Reachability.reachabilityForInternetConnection()
  reachability?.whenReachable = reachabilityNotifier
  reachability?.whenUnreachable = reachabilityNotifier
  try reachability?.startNotifier()
  self.reachabilitySink.sendNext(reachability!.currentReachabilityStatus)
} catch let error as NSError {
  self.reachabilitySink.sendFailed(error)
}

Then in a view controller or view model somewhere you can update a label like so...

DataManager.sharedInstance.reachabilitySignal
  .observeOn(UIScheduler())
  .observeNext { [weak self] (reachabilityStatus: Reachability.NetworkStatus) in
      var statusMessage = ""
          switch reachabilityStatus {
          case .NotReachable:
            statusMessage = "Offline"
            break
          case .ReachableViaWiFi:
            statusMessage = "Connected"
            break
          case .ReachableViaWWAN:
            statusMessage = "Connected"
            break
          }
          self?.onlineStatusLabel.text = "Network is \(statusMessage)"
    }

There are concepts in there like the elimination of State and why are we putting [weak self] in there.  This post would become too long and boring if I were go down those roads, so I'll save each of those concepts for it's own post.

Drawbacks and Issues

  • As your app grows, the DataManager can get pretty large, and less straight forward.  Better to do more a more MVVM pattern in this situation.
  • Using a Singleton pattern does introduce a lot of application state meaning mutable properties of some kind most likely.  And Functional programming is about removing state.  RAC works around this issue a little by providing it's own version of a property.  A  MutableProperty, which is essentially state, but bridges the stateful and stateless patterns.
  • If you are using MVVM there can be a pretty long chain required for doing simple things.  Your ViewController would subscribe to a signal from the ViewModel, which subscribes from the DataManager, which subscribes from either the Service or Persistent client.  It's hard to feel like you are constructing the structure of your app correctly when doing things like this.  Though it does make things more testable.

RAC Topics

There are a ton of paths to go down, concepts to explore.  If you have made it this far, leave a comment with what you would like to know more about as it relates for Functional Reactive Programming, or about RAC 4 in general.