Jan Gorman

Buttery smooth scrolling!

Providers

As you’ll know watchOS 2 allows you to create your own complications. One thing that really stood out to me is the idea of using providers instead of setting either text or images directly. There’s the abstract base class CLKTextProvider and CLKImageProvider that you provide (boom) to your complication. It’s the context in which the complication is rendered that decides on the actual on-screen representation of information.

So there’s this app I used to work on that needs to display prices a lot. And depending on the context where this prices is displayed it renders differently. Sounds similar to what the complication does. So in a grossly oversimplified example, let’s build something around providers using Swift:

1
2
3
4
5
6
7
struct PriceTextProvider {

    let basePrice: Double
    let reducedPrice: Double
    let vat: Double

}

This is our base provider. I think this close to actually showing the prices on screen it’s fine to be using Double. Otherwise use Int and divide by 100, always. Especially when crossing over system boundaries (APIs!) where you can never be sure of language specific rounding behaviour.

Next come our options on what we want to show using the new and great OptionSetType:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct PriceTextRenderOptions: OptionSetType {

    let rawValue: Int

    init(rawValue: Int) {
        self.rawValue = rawValue
    }

    static let Base = PriceTextRenderOptions(rawValue: 1)
    static let Reduced = PriceTextRenderOptions(rawValue: 2)
    static let Vat = PriceTextRenderOptions(rawValue: 4)
    static let BaseAndReduced = [Base, Reduced]
    static let FullPrice = [Base, Reduced, Vat]

}

And context:

1
2
3
enum PriceTextContext {
    case Normal, Short
}

Of course we could also opt to just have a context enum that then actually decides which rendering options to use. Maybe we should, I’m undecided.

And now the renderer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class PriceTextRenderer {

    let priceFormatter: NSNumberFormatter
    let vatFormatter: NSNumberFormatter

    init(priceFormatter: NSNumberFormatter, vatFormatter: NSNumberFormatter) {
        self.priceFormatter = priceFormatter
        self.vatFormatter = vatFormatter
    }

    func render(provider: PriceTextProvider, context: PriceTextContext, options: PriceTextRenderOptions) -> NSAttributedString {
        let attributedPrice = NSMutableAttributedString(string: "")
        let glue = context == .Normal ? "\n" : " "

        if let basePrice = priceFormatter.stringFromNumber(NSNumber(double: provider.basePrice)) where options.contains(.Base) {
            let a = NSAttributedString(string: basePrice, attributes: [NSForegroundColorAttributeName: UIColor.greenColor()])
            attributedPrice.appendAttributedString(a)
        }
        if let reducedPrice = priceFormatter.stringFromNumber(NSNumber(double: provider.reducedPrice)) where options.contains(.Reduced) {
            let a = NSAttributedString(string: "\(glue)\(reducedPrice)", attributes: [NSForegroundColorAttributeName: UIColor.redColor()])
            attributedPrice.appendAttributedString(a)
        }
        if let vat = vatFormatter.stringFromNumber(NSNumber(double: provider.vat)) where options.contains(.Vat) {
            let a = NSAttributedString(string: "\(glue)\(vat)")
            attributedPrice.appendAttributedString(a)
        }

        return attributedPrice
    }

}

There’s a few things going on here. So let’s brake it down:

First we’re supplying the renderer with our NSNumberFormatters. Still I see people displaying prices without using formatters. Stop it, you’re doing it wrong. Even if your designers or you insist on really specific formats (though I’d always argue to rather go with the locale defaults), you can fine tune every last bit of the formatter to your liking.

Next up is the render method. You’ll probably want to really fine tune this part. Ideas that come to mind are a .Short format that removes decimal places if appropriate, drops certain parts of the price and things like glue words that can be prepended or formatted in a specific way. E.g. VAT: %s. Or maybe work out the reduction in price and highlight that. People love a bargain.

So finally calling the whole thing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let locale = NSLocale(localeIdentifier: "de_DE")

let priceFormatter = NSNumberFormatter()
priceFormatter.numberStyle = .CurrencyStyle
priceFormatter.locale = locale

let vatFormatter = NSNumberFormatter()
vatFormatter.numberStyle = .PercentStyle
vatFormatter.locale = locale

let renderer = PriceTextRenderer(priceFormatter: priceFormatter, vatFormatter: vatFormatter)

let provider = PriceTextProvider(basePrice: 20.00, reducedPrice: 15.00, vat: 0.19)
renderer.render(provider, context: .Normal, options: [.Base, .Reduced, .Vat])
renderer.render(provider, context: .Short, options: [.Base, .Reduced])

Get the whole thing as a playground over at this github gist.

Automated Canary Builds

Like many iOS projects, yours probably also has external code dependencies. There’s a number of options how to manage them. You can do it manually by including other projects into your workspace or automate the whole process with tools such as Cocoapods, the newer Carthage or the little known peru, which functionally sits somewhere between manually managing dependencies and Carthage.

Whichever way you go, you should always integrate against known versions of these libraries to ensure that builds are reproducible. You’ll probably want to stay up to date with newer releases to receive security and bug fixes or performance improvements but at the same time not spend too much effort on manually updating them and verifying that there aren’t any bugs. This is were a nightly Canary Build comes into play that automatically checks for any updated libraries, creates a build, and runs your tests. A successful build indicates that it’s safe for you to update.

I’ll focus on Cocoapods here, since that’s the one we use at work and also has a nice option to check for new versions of pods. In its simplest form a Podfile looks like this:

1
2
source 'https://github.com/CocoaPods/Specs'
pod 'AFNetworking'

No version information whatsoever. But running pod install will also generate a Podfile.lock (which you should always check in to your repository). In the past I’ve shied away from doing this or the loosely versioned way of defining a dependency with e.g. pod 'AFNetworking', '~> 2' because I wanted to be able to see which version of a library is included at a glance.

So in my case, the Podfile might look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
source 'https://github.com/CocoaPods/Specs'

platform :ios, '7.0'
xcodeproj 'AwesomeProject'

pod '1PasswordExtension', '1.1.1'
pod 'AFNetworking', '2.5.0'
pod 'AFNetworkActivityLogger', '2.0.3'
pod 'CocoaLumberjack', '1.9.1'
pod 'DBCamera', '2.3.6'
pod 'TTTAttributedLabel', '1.10.2'

Cocoapods comes with the very handy outdated command to find out about any new versions:

1
2
3
4
5
6
7
8
9
10
11
$ pod outdated

Updating spec repositories
Analyzing dependencies
The following updates are available:
- 1PasswordExtension 1.1.1 -> 1.1.2 (latest version 1.1.2)
- AFNetworkActivityLogger 2.0.3 -> 2.0.3 (latest version 2.0.4)
- AFNetworking 2.5.0 -> 2.5.0 (latest version 2.5.1)
- CocoaLumberjack 1.9.1 -> 1.9.1 (latest version 2.0.0)
- DBCamera 2.3.6 -> 2.3.6 (latest version 2.3.13)
- TTTAttributedLabel 1.10.2 -> 1.10.2 (latest version 1.13.2)

And then I’d usually go in by hand, update the Podfile, run install and build the project. Obviously not the best use of anyone’s time. So this is where the Canary Build comes into play. As part of a Jenkins build script (I like ruby) you could do something like the following to automatically update a strictly versioned Podfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def update_pods
  updates = Hash[%x{pod outdated}
    .lines("\n")
    .select { |line| line.start_with?('-') }
    .collect { |line|
      match = /(?<pod>[[:alnum:]]{1,}).{1,}(?:[latest version])(?<version>[0-9.]{1,})/.match(line)
      [match['pod'], match['version']]
    }
    .map { |key, value| [key, value] }
  ]

  return if updates.empty?

  lines = IO.readlines('Podfile').map do |line|
    if line.start_with?('pod')
      match = /pod\s['|"](?<pod>[[:alnum:]]{1,})["|']/.match(line)
      if !match.nil? && updates[match['pod']]
        pod = match['pod']
        line = "pod '#{pod}', '#{updates[pod]}'"
      end
    end
    line
  end

  File.open('Podfile', 'w') do |file|
    file.puts lines
  end
end

A little bit of regex magic to extract the pod name and new version into a hash which we can match against the Podfile and update if needed. Then the script would go off and run pod update, build and run tests and maybe even upload to HockeyApp or TestFlight and send out an email with which pods it updated.

But of course once you start automating this, there is no need to actually version the pods anymore since you’ll have the generated Podfile.lock and/or let the script inform you about any pods it did update. In such a case it’s enough to simply:

1
2
3
4
5
6
7
8
9
def update_pods
  updates = %x{pod outdated}
    .lines("\n")
    .select { |line| line.start_with?('-') }
  return if updates.empty?
  %x{pod update}
  %x{xctool test}
  # Send out list of updated pods via email
end

A similar approach should also be possible using Carthage if you’re willing to go without fixed versions since it will generate a Cartfile.resolved with a fixed version used for the build.

Wrap-up

We have several Jenkins jobs running already for different branches and pre-release versions. Adding a nightly Canary Build is a logical next step and I’d urge anyone to give it a try. The effort to set it up is fairly low but it does free up a lot of time in the long run and should also help with the overall stability of your apps. I’d love to hear about your ideas or experiences with such a process. Get in touch on Twitter.

Better MVC

I had been meaning to write this for a while now. And even if the examples are all in Swift (because shiny) the same can be applied to Objective-C code as well without any problem.

Slimming down your iOS view controllers is a big topic around the office and there was even an entire issue of objc.io centered around the topic (as well as another one on architecture).

We had also tried some MVVM as well as Viper (ok, being an avid Uncle Bob clean code watcher and reader, I know this is about a lot more but imho doesn’t apply too well to iOS apps since there is only one presenter) but neither of those models really stuck. If you look at what Wikipedia has to say about MVC you will notice that it mentions the model notifying its associated views and controllers. Aha! So why not try that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class SimpleView: UIView {
  
  @IBOutlet weak var nameTextField: UITextField!
  weak var model: SimpleModel! {
      didSet {
          model.addObserver(self, forKeyPath: "name", options: .New, context: &context)
      }
  }

  

  override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject:AnyObject],
                                       context: UnsafeMutablePointer<Void>) {
      if context == &self.context {
          nameLabel.text = "Hi there, \(change[NSKeyValueChangeNewKey]!)"
      } else {
          super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
      }
  }

  @IBAction func didSubmit(sender: AnyObject) {
      controller.didSubmitName(nameTextField.text)
  }
}

The view takes care of all it’s own presentation and not the controller (as you’ll see in code most of the time). Now of course KVO can get pretty cumbersome when there are a lot of properties involved but you get the point. The controller has nothing to do with the presentation of the model and just received requests from the view to update the model. What does the controller look like?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protocol SimpleController: class {

    func didSubmitName(name: String)

}

class SimpleViewController: UIViewController, SimpleController {

    let model = SimpleModel()

    override func viewDidLoad() {
        super.viewDidLoad()

        let mainView = self.view as SimpleView
        mainView.controller = self
        mainView.model = model
    }

    func didSubmitName(name: String) {
        model.name = name
    }

}

Ok, very simple example indeed. What about something more involved:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class AdvancedView: UIView, UserModelObserver, RemoteModelObserver {
    
    weak var userModel: UserModel! {
        didSet {
            userModel.addObserver(self)
        }
    }
    weak var remoteModel: RemoteModel! {
        didSet {
            remoteModel.addObserver(self)
        }
    }
    
}

As you can see, the model implements two protocols this time and listens to two different models for changes. And again, the controller is very slim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class AdvancedViewController: UIViewController {

    let userModel = UserModel()
    let remoteModel = RemoteModel()

    override func viewDidLoad() {
        super.viewDidLoad()

        let advancedView = view as AdvancedView
        advancedView.controller = self
        advancedView.userModel = userModel
        advancedView.remoteModel = remoteModel
    }

    func submit(#firstName: String, lastName: String) {
        userModel.firstName = firstName
        userModel.lastName = lastName
        userModel.validate()
    }

    func load() {
        remoteModel.load()
    }

}

Any validation logic is done inside the models (which makes it easily testable). Code for loading remote resources is also done in the model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func load() {
    if let URL = NSURL(string: Constants.URLString) {
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(URL) {
            (data, response, error) in
            if error != nil {
                println("Epic Fail")
                return
            }

            var jsonError: NSError?
            let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments,
                    error: &jsonError) as NSArray
            self.comments = json
            dispatch_async(dispatch_get_main_queue()) {
                self.notifyObservers()
            }
        }
        task.resume()
    }
}

I’ve uploaded a sample project over on github including a third example of a UITableViewController and some test code.

Design Patterns in Swift: Adapter Pattern

Already December! Time for a new chapter on applying design patterns in Swift. This time it’s the Adapter Pattern’s turn. Good stuff! And simple!

So what is it and what can it do for you? The Adapter Pattern converts the interface of one class into another interface. That’s it. And with this simple pattern you can let classes work together that otherwise couldn’t.

So let’s assume you have the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protocol MusicPlayer {

    func insertMedia()
    func play()

}

class CassettePlayer: MusicPlayer {

    func insertMedia() {
        println("Insert mixtape")
    }

    func play() {
        println("Push down clunky button and play")
    }

}

Clearly, this kind if thing is only acceptable in the 80s.

Fast forward to now, Spotify, beats, you name it. How do you travel back in time and get a client that accepts a MusicPlayer to stream and play a track? You adapt it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
protocol MediaPlayer {

    func getMedia(title: String)
    func play()

}

class StreamingMediaPlayer: MediaPlayer {

    func getMedia(title: String) {
        println("Acquiring \(title) from the cloud")
    }

    func play() {
        println("Playing!")
    }

}

// MARK: Adapter in action

class StreamingMediaPlayerAdapter: MusicPlayer {

    let player: StreamingMediaPlayer

    init(player: StreamingMediaPlayer) {
        self.player = player
    }

    func insertMedia(title: String) {
        player.getMedia(title)
    }

    func play() {
        player.play()
    }

}

Jaws drop in amazement. But now consider your existing project that you want to spice up with some of that Swift. You’ve written your amazing new classes, time to integrate with Objective-C. So you head over to Using Swift with Cocoa and Objective-C only to find that the new goodness doesn’t all work. All of these aren’t compatible with Objective-C:

  • Generics
  • Tuples
  • Enumerations defined in Swift
  • Structures defined in Swift
  • Top-level functions defined in Swift
  • Global variables defined in Swift
  • Typealiases defined in Swift
  • Swift-style variadics
  • Nested types
  • Curried functions

Not to despair though, you can still go ahead and be as idiomatic in Swift as you want. With some extra effort you can get the old to talk to the new. Consider a Swift only protocol that just needs to use a tuple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protocol Legend {

    func doSomething() -> (String, String)

}

class IAmLegend: Legend {

    func doSomething() -> (String, String) {
        return ("very", "important")
    }

}

func doSomethingWithLegend(legend: Legend) {
    let (first, second) = legend.doSomething()
    // Do something else with these variables
}

Important stuff going on. You get the idea. But obviously you won’t be able to call that from any existing code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@objc class Compatible {

    let first: String
    let second: String

    init(first: String, second: String) {
        self.first = first
        self.second = second
    }

}

class LegendSwiftAdapter: Legend {

    let compatible: Compatible

    init(compatible: Compatible) {
        self.compatible = compatible
    }

    func doSomething() -> (String, String) {
         return (compatible.first, compatible.second)
    }

}

@objc class LegendObjcAdapter {

    func doSomethingWithATuple(compatible: Compatible) {
        let adapter = LegendSwiftAdapter(compatible)
        doSomethingWithLegend(adapter)
    }

}

I hope it’s somewhat clear what’s going on. Contrived example maybe… I’ll upload a more practical application soon-ish. Anyways, that’s the Adapter Pattern applied in Swift for you. As always the code is available as Xcode playground on github.

Design Patterns in Swift: Command

Continuing on in the series, lets have a look at the Command Pattern and how to implement it in Swift. As Wikipedia so eloquently defines it

In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time.

The encapsulation part is key. Say you have a bunch of different objects that can all do something and you want to expose those in a unified kind of way then the command pattern is your friend. Another great feature is that it allows for undos of those actions as you can keep a stack of the commands you ran and just pop them off the stack with an undo method. So what does that look like? First you define your command protocol:

1
2
3
4
5
6
protocol Command {

    func execute()
    func undo()

}

Easy enough. Lets get concrete:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Light {

    func on() {
        println("The light is on")
    }

    func off() {
        println("The light is off")
    }

}

class LightCommand: Command {

    let light: Light

    init(light: Light) {
        self.light = light
    }

    func execute() {
        light.on()
    }

    func undo() {
        light.off()
    }

}

Apart from producing a bunch of code that wraps the obvious nothing magic has happened yet. But now imagine you have some other appliance that also has an on/off kind of functionality but with different method signatures:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Heating {

    func turnUp(degrees: Int) {
        println("The heating is set to \(degrees)°C")
    }

    func turnOff() {
        println("The heating is off")
    }

}

class HeatingCommand: Command {

    let heating: Heating

    init(heating: Heating) {
        self.heating = heating
    }

    func execute() {
        heating.turnUp(23)
    }

    func undo() {
        heating.turnOff()
    }

}

Metric of course.

And it gets neater: There’s of course nothing to stop you from bunching together multiple method calls into a single command. So to continue with the home automation theme, you could have a macro type command ArriveAtHomeCommand that switches on a bunch of lights, sets the heating to a comfortable level and switches on the TV.

Too much code! More cryptic! Ok, ok. So you can also do a similar thing using closures that are your commands. The simplified way to define a closure makes that at least a bit more readable than it was in Objective-C:

1
2
3
4
5
6
7
8
9
10
11
12
13
typealias CommandClosure = () -> Void

var commands = [CommandClosure]()

let heatingCommand = { () -> Void in
    let heating = Heating()
    heating.turnUp(23)
}

commands.append(heatingCommand)

// Much later
commands[0]()

That also works. The option to store closures/functions inside of arrays is pretty cool but here you loose the build in undo option. The way around that would be to define both an execute and undo block and whenever you execute a command you push its corresponding undo into your array/stack. But if you’re only going one way and can skip the undo, this is a viable way to go.

Again the code is available as Xcode playground on github.

Design Patterns in Swift: Strategy

As a refresher, I thought it could be fun to look at some common design patterns and how they apply to Swift. One very essential part of the pattern-tool-chest is the strategy pattern. Let’s dive straight in.

With the strategy pattern you define algorithms or behavior. You then compose your objects out of those behaviors. How does that look like?

First, your behavior protocol and two possible implementations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protocol TapBehavior {

    func tap()

}

class CartTapBehavior: TapBehavior {

    func tap() {
        println("I'm the cart tap")
    }

}

class WishListTapBehavior: TapBehavior {

    func tap() {
        println("I'm the wish list tap")
    }

}

Which brings up an important point: it’s always preferrable to program to a protocol/interface rather than to a concrete implementation.

Next, you’d want to actually use the behavior:

1
2
3
4
5
6
7
8
9
10
11
class SomeViewWithAButton: UIView {

    @IBOutlet weak var aButton: UIButton!

    var tapBehavior: TapBehavior?

    @IBAction func didTapButton(sender: AnyObject) {
        tapBehavior?.tap()
    }

}

By making the behavior a property of the class it is now easy to add and replace behaviors at runtime. You might begin to see how this can lead to very flexible designs. A different approach here could have been to create an abstract base view and then create two concrete implementations for different tap behaviors but as soon as you need a new kind of behavior you’d be forced to create a new subclass. And now imagine that you have multiple behaviors in a class – the subclass approach would lead to all kinds of combinations of subclasses that each have to implement variations of behavior.

Even if this is an extremely simple pattern, it’s good to keep it in mind the next time you have to implement varying behavior in some kind of base class. Would composing work better than inheriting?

A full example is available as Xcode playground on github

iOS Storage

When it comes to persistence for iOS there are a few options to choose from:

Which one you end up using of course depends on your use case and each of the solutions has some tradeoff with regards to read/write performance and implementation complexity.

Background

At work we had been using Core Data with Magical Record shielding us from some of the gory implementation details when it comes to wrangling with different NSManagedObjectContext and getting out of the users main thread.

Another promise of MagicalRecord are “free” lightweight core data migrations using [MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"storage.sqlite"] and so one fateful release we decided to kill off an old, unused model. Prior tests revealed no issues going ahead with the migration but a certain combination of being logged in to the app and adding something to your shopping cart resulted in the dreaded Can't merge models with two different entities named … error. A revert and a fast-track approval by Apple saved the day but confidence in MR and Core Data was… a bit shaken.

Enter Yap

I had privately been playing around with YapDatabase and liked it. A lot. Concurrency, views, it being a key-value storage built on top of SQLite and especially the concept of YapDatabaseViewRowChange for updating table views made for compelling features.

So I pitched the idea at work and we migrated over some Core Data tables to Yap. One thing that became obvious during the development was that Yap requires quite a bit of boilerplate code to set up. You always end up creating views, long lived transactions and managing NSNotification to update said transactions. But I rationalized it as being a one time effort and chugged along.

After the release our Crashlytics popped up with an unnerving number of Yap related crashes. Not all, but most having to do with notifications being sent to deallocated observers. This seemed rather strange as we were removing the observer correctly on deallocation and never found a root cause. Stability of the app got so bad though that a hotfix release was scheduled and Yap was replaced.

Enter NSKeyedArchiver

We went back to the drawing board and considered our options. We didn’t want to deal with Core Data’s complexity any longer and reliance on complex third party libraries had left a sour taste. What do we know:

  • Storage has to run in the background and not block the main thread
  • We don’t have any big tables… the biggest one needs to store 100 entries. (Others are out of our control because customer’s fill them so a huge buffer would set an upper limit of 500 entries)
  • It needs to be simple, every one on the team should immediately know what’s going on
  • No third party library if possible
  • No need to store anything in iCloud, any syncing happens between the app and our own servers

NSKeyedArchiver gets a bad wrap for being slow, and yes, try to store a lot of values (in the thousands!) and it degrades pretty badly but for the use case stated above of maybe 500 entries it actually is pretty decent. Xcode 6 adds the handy [self measureBlock:^{}], time for some benchmarks.

  • Yap scored a write performance of 0.005 seconds. Great result
  • FastCoding came in a respectable second with 0.013 seconds
  • NSKeyedArchiver scored last with 0.110 seconds

But, and this is a huge but, it is fast enough for our needs. The database (or essentially just an NSArray) is read on into memory and any changes to the data also happen in memory and it actually is very snappy to use. Persisting to disk is done on a background thread using an NSOperationQueue with a size of one so all additions and deletes queue up nicely and there are no nasty concurrency issues to deal with.

A neat side effect was that we also don’t need separate models for Core Data and our API anymore. We use Mantle extensively and the cool thing is that all MTLModel subclasses also comply to <NSCoding>. We can pass the same values back and forth.

Learning

  • Always know your real use case
  • Benchmark!
  • Don’t rely on third party libraries as much. Cocoapods are awesome but sometimes simple does it.
  • Find edge cases during your QA phase