Breaking down Custom View Controller Animations with Moves

When I first learned to program for iOS, I was always interested in how view controller animations worked. How did some apps have such cool animations when all I can is present a full sized modal over my current screen?

I love keeping up with what’s trending in swift on github because there’s always at least one cool project that inspires me and teaches me something. For about a quarter of those repos, I’ve noticed the library had to do with simplifying animations, specifically presenting a modal in a cool, flashy way. I’m not here to bash any of them; as a matter of fact, I’ve used and still use some of those libraries in iOS projects I work on today!

Introducing “Moves”

I’ve open sourced a view controller transition library called ‘Moves’, which makes custom transitions (modals, popups, tooltips) a whole lot easier to develop. Unlike other libraries though, Moves is not as simple or close to a 1-line solution that other animation libraries have successfully pulled of. Rather, Moves is a pretty vanilla wrapper that champions the flexibility of your own view controller by leveraging generics and the standard UIViewControllerTransitioningDelegate APIs from UIKit.

Example of a custom transition Moves can help you do

This post is about my learnings making this open sourced library. This wrapper is not perfect, and admittedly, there are a couple of points and lines of code which I don’t fully understand (more on that later), but nonetheless, I think this library is a great teaching point for students and people similar to myself who have imported animation libraries before without a good grasp of how the libraries work! Follow along with this instructional post or try out the library out yourself on cocoapods. If you open the source project, be sure to set the project scheme to ‘Moves-Tutorial’, which contains the final code sample of my walkthrough below.

pod 'Moves'


Understanding UIViewControllerTransitioningDelegate

The simplest way to create a custom view controller animation is conforming to the ‘UIViewControllerTransitioningDelegate’. This delegate is required to do one thing, and that is proposing how a starting view controller will animate to a destination view controller. This is illustrated most easily (and lazily) by having the initial view controller itself conform to the ‘UIViewControllerTransitioningDelegate’.

class MasterViewController: UIViewController, UIViewControllerTransitioningDelegate {
  
// MARK: UIViewControllerTransitioningDelegate
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  return self
}

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  return self
}

Soon enough, the Swift compiler will yell at you with

Type ‘MasterViewController’ does not conform to protocol ‘UIViewControllerAnimatedTransitioning’.


Of course, there are some required methods that this view controller must fulfill if it wants to declare itself as the transitioning delegate! Respect UIViewControllerAnimatedTransitioning’s name by adding its two required protocol methods into MasterViewController. The first method is

// MARK: UIViewControllerAnimatedTransitioning
func transitionDuration(
  using transitionContext: UIViewControllerContextTransitioning?
  ) -> TimeInterval {
  return 2
}

func animateTransition(
  using transitionContext: UIViewControllerContextTransitioning
  ) {
  // ** Add your custom animation logic here **
}

// *Method declaration weirdly newlined to improve legibility of this code block.*

The first required method simply needs to know how long you expect your custom animation to last. I set it to 2 seconds so that it’ll be easy to distinguish a slow custom animation.

The latter method ‘animateTransition(using transitionContext:’ is where the heart of your transition logic is located. Simply put, this is where you declare how your initial view controller leaves the screen, alongside how your destination view controller enters the screen. Let’s see how a simple fade-in transition would look like in this function.

func animateTransition(
  using transitionContext: UIViewControllerContextTransitioning
) {

  // Guard check for the 'to' and 'from' view controllers.
  guard let fromVC = transitionContext.viewController(forKey: .from),
    let toVC = transitionContext.viewController(forKey: .to) else { return }

  // Start with destination vc hidden
  toVC.view.alpha = 0

  // Add toVC to container view of animation
  transitionContext.containerView.addSubview(toVC.view)
  toVC.view.frame = transitionContext.containerView.frame

  let totalDuration = self.transitionDuration(using: transitionContext)

  UIView.animate(withDuration: totalDuration, animations: {
    fromVC.view.alpha = 0
    toVC.view.alpha = 1
  }) { _ in
    transitionContext.completeTransition(true)
  }
}

There’s a ton to digest here, so let’s start with what ‘transitionContext’ is about.

transitionContext is provided to us from the UIKit system when we begin a custom transition. This context object has all the information you need to orchestrate your custom animation, specifically through the ‘to’ and ‘from’ view controllers that I optionally check for in the snippet above.

After I guard check for both view controllers, I proceed with a simple setup of ‘fromVC’ by adding it’s main view onto the transitionContext’s containerView. You can think of this container view as the stage in which this entire animation takes place.

In Apple’s documentation,

All animations must take place in the view specified by the containerView property of transitionContext. Add the view being presented .. to the container view’s hierarchy and set up any animations you want to make that view move into position.

Also note that because we are performing a fade animation, I set the initial view alpha to 0.



Lastly, I perform a simple animation ‘flip-floping’ the view alphas of toVC and fromVC, which should effectively create the fade in-fade out animation we want.

UIView.animate(
  withDuration: totalDuration,
  animations: {
    fromVC.view.alpha = 0
    toVC.view.alpha = 1
  }) { _ in
  // Call this to indicatate that transition is complete
  // System performs the removal of from view controller
  // subview
  transitionContext.completeTransition(true)
}

It doesn’t work

If you ran the application at this point, you will realize that something is still not right — when I tap the “show modal” button, I still get the default modal animation given by Apple where the destination view slides from the bottom up; where’s my fade!?

That’s because we’re still missing one key piece. We haven’t told the destination view controller’s transitioning delegate that we are managing it’s transition!

@IBAction func transitionButtonPressed(_ sender: Any) {

  let vc = storyboard!.instantiateViewController(withIdentifier: "ModalViewController") as! ModalViewController
  // We are managing the destination vc's animation on its behalf.
  // As a result, the system will call the 'transitionDuration:' and
  // 'animateTransition:transitionContext:' methods we declared above
  // when coordinating this custom transition.
  vc.transitioningDelegate = self

  present(vc, animated: true, completion: nil)
}

It works 👍

The best part about this animation is that our animateTransition: logic works for both the presentation and dismissal of this view controller.

If you did not realize, it wasn’t just our presenter that illustrated the fade animation— the modal dismisser created the fade transition too! This is because our view controller declared itself as both the presenter and dismisser animator in the UIViewControllerTransitioningDelegate methods in the very beginning. As a result, the system inquires from our delegate, MasterViewController, twice, calling the same ‘animateTransition’ fade logic each time we present and dismiss the modal.

That sounds very convenient, but if you’re thinking what I’m thinking, you might be wondering how we can further customize and separate out all our transition logic from our view controller.


Enter Moves

Moves does everything we’ve talked about above, but it abstracts away the tedious parts of process, such as conforming to a delegate method just to return a duration, and casting your to and from view controllers to the exact type you expect them to be with generics; in our case it’s MasterViewController and ModalViewController. This allows us to create transitions with all the resources specific to our view controller subclasses: fading out specific collection view cells, sliding out a navigation bar, etc.

open class MovesCoordinator<
  T: UIViewController,
  U: UIViewController
  >: NSObject, UIViewControllerTransitioningDelegate {
 
  public typealias VCAnimator = Animator<T, U>
  public let presenter: VCAnimator
  public var dismisser: VCAnimator
 
  // MARK: UIViewControllerTransitioningDelegate
  public func animationController(
    forPresented presented: UIViewController,
    presenting: UIViewController,
    source: UIViewController
    ) -> UIViewControllerAnimatedTransitioning? {
    return presenter
  }
  
  public func animationController(
    forDismissed dismissed: UIViewController
    ) -> UIViewControllerAnimatedTransitioning? {
    return dismisser
  }

}

Above all else, it abstracts our custom transition business logic outside the view controller in contrast to my examples above. Our presentation and dismissal logic are separated into their own Animator classes, and we will introduce the MovesCoordinator, which takes over as the UIViewControllerTransitioningDelegate, and primary manages our presenter and dismisser animators, as well as anything else in between such as background dimming and possible panning of our modal view controller. When creating a MovesCoordinator, you simply need two animators with the same pair of view controller types, each with any configurations specific to that Animator.

lazy var movesCoordinator: MovesCoordinator<UINavigationController, SlideUpWithContextModalViewController> = {
    

  let modalConfig = ModalConfiguration()
  modalConfig.width = self.view.bounds.width * 13/15
  modalConfig.height = self.view.bounds.width * 13/15
  modalConfig.roundedCorners = [.topLeft, .topRight, .bottomRight, .bottomLeft]
  modalConfig.roundedCornersRadius = 5
      
  let presenter = FadeInOverContextAnimator<UINavigationController, SlideUpWithContextModalViewController>(
    modalConfig: modalConfig,
    duration: 0.6
  )

  let dismisser = FadeOutOverContextAnimator<UINavigationController, SlideUpWithContextModalViewController>(duration: 0.6)
  
  
  let coordinator = MovesCoordinator(
    presenter: presenter,
    dismisser: dismisser
  )
  
  // Allow pan with a dismiss threshold of 100pts
  coordinator.movesConfig.pannable = true
  coordinator.panConfig.dismissRadiusThreshold = 100
  
  return coordinator
}()

When we need to present our SlideUpWithContextModalViewController view controller, we simply call MoveCoordinator’s present: method, which abstacts the tedious boilerplate of view controller transitiong delegate setting.

let vc = storyboard!.instantiateViewController(withIdentifier: "SlideUpWithContextModalViewController") as! SlideUpWithContextModalViewController
movesCoordinator.present(vc, presentingVC: self.navigationController!)


Challenges

Dimming

Adding a dim overlay is a very frequent capability when presenting a toast or modal/tooltip in iOS. I faced some challenges when deciding where to place the dim overlay logic. Firstly, we need to store a reference of the dim view somewhere because eventually, our dismisser transition logic will need to remove it from the view hierarchy. Naturally, we want to present our dim overlay at the same time our presentation transition gets triggered, so I considered placing the dim overlay logic in the presenting Animator class. But, the issue there is that our presenting Animator and dismissing Animator are two separate objects unbeknownst of each other’s existence. Animators do not even have a weak reference to their parent MovesCoordinator. Adding a dim overlay in one animator class would not work because it’s corresponding dismisser cannot access the stored dim overlay reference.

Instead, I utilize observables in the Animator class in which I emit any relevant events from Animator to any object that subscribes to the observable properties.

open class Animator<
  PresentingVC: UIViewController,
 PresentedVC: UIViewController
 >: NSObject, UIViewControllerAnimatedTransitioning {
  
  public let events: Observable<AnimaterLifecycleEvent?> = Observable(nil)
  
  ...

  open func performAnimations(using transitionContext: UIViewControllerContextTransitioning, from presentingVC: PresentingVC, to presentedVC: PresentedVC, completion: @escaping ()-> ()) {
  
    // Publish to any subscribers that view controller 
    // transition for this animator will start.
    events.value = AnimaterLifecycleEvent.transitionWillAnimate(
      transitionContext: transitionContext
    )

    // Should be subclassed; define how the 
    // transition should perform in subclass.
  }
}

If you are not familiar with observable subjects or ReactiveX(RxSwift, RxJava, etc), you can simply think of my current use case of an Observable as a property that notifies any subscribing object of its’ changes — sort of how NotificationCenter behaves, but observables are more strongly coupled to its subscribers. (You actually need to have access to the observable property, whereas with Notifications— all you need is a string to pick up on broadcasted data.)

What do observables have to do with creating a dim overlay? Well, because if our presenter and dismisser animators are capable of emitting when they start and finish their transition, we can initiate other events in tandem with our animator events, such as presenting and hiding a dim overlay!

private func observeAnimatorLifeCycles(
  presenter: VCAnimator,
  dismisser: VCAnimator
  ) {

  for animator in [presenter, dismisser] {

    animator.events.observe { [weak self] (_, newEvent) in

    guard let strongSelf = self else { return }
    guard let event = newEvent else { return }

    switch event {
    case .transitionWillAnimate(let transitionContext):
      if strongSelf.config.showBackgroundDimView {
        strongSelf.handleBackgroundDimView(
          isPresenting: animator.isPresenter,
          transitionContext: transitionContext
        )
    }
    default:
      break
    }
    }.disposed(by: disposeBag)
  }
}

In the example above, MovesCoordinator observes its animators’ tranitionWillAnimate event, which calls handleBackgroundDimView when tranitionWillAnimate: gets fired. (Depending on whether the animator is a presenter or dismisser, handleBackgroundDimView handles the insertion or removal of our dim view, respectively.)


Extras

Contextual Animations (Experimental)

I’ve always been fascinated with Duolingo’s segue transitions in it’s iOS application. If you’ve never heard of Duolingo, it’s a simple app that helps people learn new languages with fun modular lessons you can complete on-to-go.

I’ve always wanted to replicate it and recently, Ray Wenderlich’s Dev Con, ran an animation workshop on recreating this popular animation. That workshop, led by Caroline Begbie, was a huge inspiration to me adding this contextual animation element. (If you’re interested, check out the Ray Wenderlich 2017 Vault Bundle, which provides all the videos and assignments that a RWDevCon participant received at this past year’s conference.)https://s3-us-west-2.amazonaws.com/leojkwan/images/2017-10-29-custom-vc-transition-moves/duolingo-example.mp4

Duolingo app replica example from Ray Wenderlich

From here on I will refer to any pair of views that animates from one view controller to the next as “contextual views”.

Remember that MovesCoordinator declaration I wrote out above? where we called the coordinator’s present method? Let’s register some contextual views and see what happens.

let vc = storyboard!.instantiateViewController(withIdentifier: "SlideUpWithContextModalViewController") as! SlideUpWithContextModalViewController
movesCoordinator.present(vc, presentingVC: self.navigationController!)
movesCoordinator.present(vc, presentingVC: self.navigationController!, with: { [weak self] () -> ([ContextualViewPair]) in
  
  guard let strongSelf = self else { return [] }
  
  // Register contextual views
  return [
    ContextualViewPair(strongSelf.item, vc.detailItem),
    ContextualViewPair(strongSelf.titleTextLabel, vc.detailTitleTextLabel)
  ]
})

How does this animation work?

The centerpiece to this transition is snapshot views. The views owned by each view controller never move at all. I create a snapshot over the initial view, hide the real views, then animate the snapshot where the destination view belongs. Finally, I unhide the destination view and remove the snapshot above it off the superview.

That sounds complicated so I will just show you what I mean. For demonstration purposes, I do not fully hide the contextual views; instead they are at alpha 0.2 so you can see how this animation sequence plays out.https://s3-us-west-2.amazonaws.com/leojkwan/images/2017-10-29-custom-vc-transition-moves/contextual-views-dimmed.mp4

Custom transition with 0.2 alpha contextual views for demonstration


Challenges I faced

The two challenges I faced when attempting to abstract this feature were:

  1. Decoupling the contextual view pairs as much as possible.

    If you happen to have purchased or attended the animation talk at RWDevCon, you’ll notice the example application was designed to animate just 1 pair of views. What if we want two or three contextual views animating on transition? I needed to have an easy way to register contextual view pairs, at a point where the MovesCoordinator knew the destination frames. I also did not want to force a ‘layoutIfNeeded’ because you might have interface builder logic in the viewDidLoad of your destination view controller, and prematurely triggering that will crash your application.
  2. Handling deeply embedded context views (an imageView in a UITableViewCell, in which its tableView is in a container view).

    In the Duolingo example above, the animated view is only one subview layer deep from its view controllers’ root view. Things get a lot more complicated when they are deeply nested in subviews. In order for this snapshot to animate properly, we need to calculate precisely the initial and final frames of our contextual views. Otherwise, you can imagine how this animation will look completely wrong if we miscalulate frames and attempt to flip-flop the alphas of our snapshot and actual view. This is the main reason why I’ve labeled this contextual feature as ‘experimental’, because I have not solved certain scenarios that lead to this snapshot frame miscalculation. If you’re interested in how I perform frame calculations up each contextual view’s view hierarchy, check out the private method animateContextualViews: in the Animator class.
Conclusion

The main goals for this library was to promote reusability & flexibility, not brevity; with that said, thanks for reading until the end! With this set of abstractions, developers can create a ton of common and popular view controller transitions. This is a work in progress, but I’ve been using this library in production for one my personal apps, SuperFit. Take a look again!

Contextual view controller transition in SuperFit Fitness App

Reach out to me at leojkwan@gmail.com or submit an issue on the Moves repo if you find any bugs or have a suggestion about the library. All feedback is welcome!

Living reactively in Swift, before RxSwift. And truly understanding “DisposeBags”

When I first learned to program about 2 years ago, one term that spooked me real good was this thing called Reactive Cocoa. It’s not a friendly sight of code when you see it for the first time. I remember thinking, ‘What the heck is RAC? – I’ve never learned in class at Flatiron School. Ehrm, Run.’

More recently, I decided to dig deeper into reactive programming, looking into more resources/blogs about RxSwift. You also know RxSwift has hit the mainstream of iOS swift programming recently after a dedicated book about RxSwift gets published on Ray Wenderlich … and I bought it ;).

But before trying to understand a full-fledged framework like RxSwift, I tried becoming more reactive with my code without a framework, and I enjoyed it. Let me explain.

What I did initially was leverage a native, and very simple, Swift Observable pattern I picked up from a popular Swift example project, SwiftWeather.

Since then, I’ve come to better appreciate a ‘reactive’ style of programming, especially when you add some MVVM flavor into the mix. The results were immediate to me, and I found that I wrote less boilerplate delegate/protocol code. I also don’t need to ever consider NotificationCenter(not that I used it much in the first place.) And most importantly, I reduced a ton of cognitive load when mentally trying to remember the multiple states my objects are in at any given point, specifically in view controllers.

class Observable1<T> {
  
  typealias Observer = (T) -> Void
  private(set) var observer: Observer?
  
  func observe(_ observer: Observer?) {
	self.observer = observer
  }
  
  var value: T {
	didSet {
	  observer?(value)
	}
  }
  
  init(_ v: T) {
	value = v
  }
}

I’d simply enclose a value in this class named ‘Observable’, and this object would take in one observer that subscribed to the wrapped value’s changes.

The core line lies in the ‘value’ didSet method. Every time a value is set, the observer, which is a function that accepts the wrapped value’s type, gets called with the updated value.

var value: T {
	didSet {
	  observer?(value)
	}
}

There’s really no magic to it; as another developer who realized this Observable/KVO pattern pointed out, It would follow all the existing rules of memory management and variable scope as any other closure

class ViewController: UIViewController {
  
  var currentWeather: Observable<Double> = Observable(50)
  
  override func viewDidLoad() {
    super.viewDidLoad()
   
    currentWeather.observe { (newPrice) in
      print("1. Updated Temperature: \(newPrice)")
    }
    
    currentWeather.value = 50 // 1. Updated Temperature: 50
    currentWeather.value = 51 // 1. Updated Temperature: 51
    currentWeather.value = 52 // 1. Updated Temperature: 52    
  }
}


Simple example, not realistic. In reality, I probably want multiple things subscribing to currentWeather’s changes.

class ViewController: UIViewController {
  
  var currentWeather: Observable1<Int> = Observable1(50)
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    currentWeather.observe { (newPrice) in
      print("1. Updated Temperature: \(newPrice)")
    }
    
    // Added a second observer
    currentWeather.observe { (newPrice) in
      print("2. Updated Temperature: \(newPrice)")
    }
    
    // Added a third observer
    currentWeather.observe { (newPrice) in
      print("3. Updated Temperature: \(newPrice)")
    }
    
    currentWeather.value = 50 // 3. Updated Temperature: 50
    currentWeather.value = 51 // 3. Updated Temperature: 51
    currentWeather.value = 52 // 3. Updated Temperature: 52    
    
  }
}

Looks go– Wait. That’s not right. I get print statements from only the third observer — what about the 1st and 2nd ones?

Looking back at Observable, I see that observer is a single property; so every time subscribe get called on currentWeather, the last observer gets written over by the newly passed in one.

This is when things got difficult.

At first thought, the most practical thing to do in order for Observable to push changes to multiple observers is to change observer: Observer<T> to an observers: [Observer<T>]. Sounds like a quick and easy fix!

class Observable<T> {
  
  typealias Observer = (T) -> Void
  private(set) var observers: [Observer] = [] // change to an array

  func observe(_ observer: @escaping Observer) {
    // append observer to array
    observers.append(observer)
  }
  
  var value: T {
    didSet {
      // iterate over observers and call each closure newly set value
      observers.forEach({$0(value)})
    }
  }
  
  init(_ v: T) {
    value = v
  }
}


There. Now we should be able to notify every function/observer in our observers array.

currentWeather.observe { (newPrice) in
      print("1. Updated Temperature: \(newPrice)")
}
    
currentWeather.observe { (newPrice) in
      print("2. Updated Temperature: \(newPrice)")
}
    
currentWeather.observe { (newPrice) in
      print("3. Updated Temperature: \(newPrice)")
}
    
currentWeather.value = 51
currentWeather.value = 52
currentWeather.value = 53
// 1. Updated Temperature: 51
// 2. Updated Temperature: 51
// 3. Updated Temperature: 51
// 1. Updated Temperature: 52
// 2. Updated Temperature: 52
// 3. Updated Temperature: 52
// 1. Updated Temperature: 53
// 2. Updated Temperature: 53
// 3. Updated Temperature: 53


Sweeeet.

This is very similar to what RxSwift does with subscribe(...) and Variable. Here’s an example of what an observable array of strings would look like.

import RxSwift

class ViewController: UIViewController {
  
  let disposeBag = DisposeBag()
  let names = Variable(["Leo"])

  override func viewDidLoad() {
	super.viewDidLoad()
	
	names.asObservable().subscribe { (updatedArray) in
	  print(updatedArray.element ?? "no element")
	}
	.addDisposableTo(disposeBag)
	
	names.value.append("John")
        // ["Leo"]
        // ["Leo", "John"]
  }
}

Now there’s one clear difference between my example and RxSwift’s example of an Observable. That’s the ‘DisposeBag’.


Enter DisposeBag rabbit hole.

It was only after using my own Swift Observable implementation where I realized I was missing something critically important.

The observers are never deallocated. If you are observing the weather in a detail view controller and pop back to the root view, the detail view controller should be deallocated, along with anything owned by that view controller.

The problem with our Observable implementation is that after adding an observer to our Observable, we don’t know how to remove it when the observer’s associated object is deinitialized. We need a mechanism for the observable, like currentWeather above, to differentiate its active observers from observers that are no longer referenced anywhere.

Jared Sinclair brought up a great point about marking each observable with a token/unique key. Instead of just an observables array, we’ll use a dictionary that gives each observer a unique key; when a new observer is inserted, we return it’s key.

This is when the concept of a dispose bag is needed. A bag is simply a collection of things that are not ordered, and can have repeated things in it, unlike a set. Similar to RxSwift, we’ll use a ‘DisposeBag’ that stores all of our observer’s unique keys. In addition, this bag needs to trigger the removal of every observer that is referenced in our bag from our Observable when it’s owner deallocates(a view controller in our example.)

That was a difficult sentence to understand, so I’ll break it down using our weather temperature above. When we start the application, our root view controller, VC1, subscribes one observer. When we push into the detail view controller, VC2, we subscribe another observer.

On subscribe, we return a Disposable, which is just an object that represents the key associated with that observer. We need to take that Disposable and place it a DisposeBag within VC2. It must be in the local scope of VC2 because when we pop the view controller and deinitialize VC2 and any references VC2 owns, our dispose bag needs to be on of them.

class MyDisposeBag {
  
  var disposables: [Disposable] = []
  
  func add(_ disposable: Disposable) {
    disposables.append(disposable)
    print("new dispose bag count: \(disposables.count)")
  }
  
  func dispose() {
    disposables.forEach({$0.dispose()})
  }
  
  // When our view controller deinits, our dispose bag will deinit as well
  // and trigger the disposal of all corresponding observers living in the
  // Observable, which Disposable has a weak reference to: 'owner'.
  deinit {
    dispose()
  }
}

And it works! We have a crude, but working Observable implementation written in Swift. It doesn’t leak memory and properly disposes of dereferenced closures. It allows multiple observers to subscribe to an Observable and enforces compile-time type safety by using generic properties and classes. Lastly, it doesn’t require pulling in a full-fledged reactive framework like RxSwift.

Check out the final example here Gist

In a future post, I’ll dive into some of the bells and whistles that come with using RxSwift! There’s a lot!

Easy Networking and Testing with Moya

One of the things I’ve done most in iOS programming is create ad hoc networking layers that encapsulate NSURLSession. When I integrate any 3rd party service with a RESTful interface , I’ll often create an APIManager/APIService of some sort which houses my URLSession, along with the handful of finely named methods my app would do with the service.

struct InstaFoodAPIService {
    private let requestManager = RequestManager()

    func createUser(firstName: String, lastName: String, completion: (_ success: Bool)-> Void) {
        // requestManager.POST...
        // Handle returned data here
    }

    func fetchUser(firstName: String, completion: (_ user: User?)-> Void) {
        // requestManager.GET...
        // Handle returned data here
    }
    func fetchAllFriends(for user:User, completion: (_ users: [User])->()) {
        // requestManager.GET...
        // Handle returned data here
    }
} 

It’s actually not bad code. You are encapsulating concerns when you seperate your api service business logic from a request manager, which houses your either your own custom network client, or a popular library such AlamoFire or AFNetworking.

Here’s a real world example of a request manager I’ve used before (Full code example at the end)

public typealias RequestResponse = (_ statusCode:Int, _ data:AnyObject?) -> Void

struct RequestManager {
    
    static func makeHTTPSRequest(
        _ token: String?,
        postBody: AnyObject? = nil,
        methodString:String,
        urlString:String,
        completion: @escaping (RequestResponse)) throws {
            
            // URLSession setup code
            // ...

        // Create a data task object
        let task = session.dataTask(with: (request as URLRequest), completionHandler: {(data, response, error) in 
            // Parse Data
            if let data = data {
                
                if let dataDict = try? JSONSerialization.jsonObject(with: data, options: [.allowFragments]) {
                    completion(response.statusCode, dataDict as AnyObject?)
                } else {
                    completion(response.statusCode, data as AnyObject?)
                }
            } else {
                // Successful request- no data, send status code
                completion(response.statusCode, nil)
            }
        })
    })

This network client does one thing which is make a network request. The setup is straightforward since we’re encapsulating over a vanilla shared URLSession. The static method takes in an optional access token for user protected requests, as well as a ‘postBody’ object, for POST requests.

As time goes on, I’ll inevitably have to do more customized things with my request manager. For example, I may need to make a download task for larger sized files like images and video. Or, I may need to post a form and encode my post body with a form-encoded url. A ton of ifs and maybe’s can happen, which is why libraries such as AlamoFire and AFNetworking are useful since just about any network request you’ll have to make is wrapped in one place — not to mention it’s powered by the culture of open-source, where tons of contributers maintain it, and even more companies/apps use it in production!

But that’s the networking layer. You still have to encapsulate your seperate service layers however you do it in your application. Maybe you’ve awesome and you build a generic request manager for your twitter, github, facebook RESTful interfaces… or maybe you’re like me and decide to look past the duplication and make a small, teensy manager just for mailchimp. Just a small class that does one thing. I mean, it could just live on it’s own right?

No.

You’re going to look back at your code months from now with 4-5 different “little” network layers and wonder, “where is that code that makes the request to fetch my email lists again?”


Enter Moya.

An abstraction layer over the popular AlamoFire with the goal that it’s your one and only abstraction layer. It means you’re going to have to buy in to the library, but If popularity and open-source maintainability is your concern, look again.

I haven’t used Moya in any Production application but here are a few reasons why I like the look of it.

All relevant service logic is encapulated in one placeIn Moya, your 3rd party service endpoints are seperately defined as enums with its listed endpoints as your enum cases. The one similarity your enums must enforce is the ‘TargetType’ Protocol. If you’re not well in tuned with protocols in Swift, check out my post on delegation and protocols.

Like I mentioned earlier about our first request manager, you still have to separate each of your services, indicating it’s base url, params, header and encoding logic somewhere. While it’s not terribly hard to stay organized and separate your different services, it is two times as simple to be lazy and sprinkle networking code all across your app. That said, you eventually will get lost 2-3 months from now.The great thing about working with Moya is that in order to even get the library up and running, you’re enforced to be structured and separate targets from the start! Double win.It’s best understood when examining the ‘TargetType protocol’.

Here’s an example of what your ‘TargetType’ enum requires when declaring a service(API you are making requests against; facebook, mailchimp, stripe) in Moya. (Adapted and slightly modified from Moya’s setup instructions)

  extension InstaFoodService: TargetType {
        
        var baseURL: URL {
            return URL(string: "https://api.instafood.com")!
        }
        
        var path: String {
            switch self {
            case .createUser(_, _):
            return "/user"
            }
        }
        
        var method: Moya.Method {
            switch self {
            case .createUser:
            return .get
            }
        }
        
        var task: Task {
            switch self {
            case .createUser:
            return .request
            }
        }
        
        var parameters: [String: Any]? {
            switch self {
            case .createUser(let firstName, let lastName):
            return ["first_name": firstName, "last_name": lastName]
            }
        }
        
        var parameterEncoding: ParameterEncoding {
            switch self {
            case .createUser:
            // Send parameters as JSON in request body
            return JSONEncoding.default
            }
        }
        
        var sampleData: Data {
            switch self {
            case .createUser(let firstName, let lastName):
            let userJson = [
                "firstName": firstName,
                "lastName": lastName
            ]
            return jsonSerializedUTF8(json: userJson)
            }
        }
        
        // Helper
        private func jsonSerializedUTF8(json: [String: Any]) -> Data {
            return try! JSONSerialization.data(
                withJSONObject: json,
                 options: [.prettyPrinted]
                 )
            }
        }

Moya is designed to enforce endpoint testability.

Like I said, the crux of Moya lies in this the ‘TargetType’ protocol. But one requirement that really stuck out to me was the required ‘sampleData’ variable. Initially I thought this would be an optional objective-c protocol, but no — you need to define what data you expect to be returned from each of our endpoints. I don’t always unit test my code, but anyone buying into Moya will have a much easier time testing his/her endpoints, since you’ll have already established your stubbed data. My one concern is that this requirement brings up the debate at to whether or not you should mock types you don’t own.

Moya leverages compile time checking for any request you’re intending to make.

Because your services are represented as enums, your url params can be represented in the shape of an Enum’s associated values, making it 4.5 times (this may vary :O) harder to make screw up a network request. For example, when interacting with the example InstaFood service above, the ‘createUser’ POST endpoint required ‘firstName’ and ‘lastName’ in the post body.

 extension InstaFoodService: TargetType {
        // ...

        var parameters: [String: Any]? {
            switch self {
                case .createUser(let firstName, let lastName):
                return ["first_name": firstName, "last_name": lastName]
            }
        }

        // ...
        }

In the parameters field of my InstaFood service type, I can layout how the post body should look like by passing the associated values I receive from the ‘.createUser’ case into a firstName, lastName dictionary. Power of enums!


Making the request with MoyaProvider

Remember the ‘RequestManager’ from above. ‘MoyaProvider’ is now your request manager. It requires a generic type on creation, and that’s right— you guessed it, the generic type must conform to the ‘TargetType’ protocol. How convenient! Our InstaFoodService enum fits right into that requirement, so when we do need to pull from the InstaFood API, it would look something like this.

struct User {
    let firstName: String
    let lastName: String
}

class ViewController: UIViewController {
  
  private let instaFoodService = MoyaProvider<InstaFoodService>()

  override func viewDidLoad() {
    super.viewDidLoad()

    let newUser = User(firstName: "Leo", lastName: "Kwan")    
    
    instaFoodService.request(.createUser(
        firstName: newUser.firstName,
        lastName: newUser.lastName
        )
    ) { (result) in // Result<Moya.Response, MoyaError>
      
      switch result {
        
      case .success(let response):

        // a 200 because requests are too easy now.
        let statusCode = response.statusCode

        // Do something after we create a new user

      case .failure(let error): break
        
        // Could not make a network request
        // Maybe we should try again when there is internet?
        print(error)
      }
    }
    
  }
}

What you’re left with is a straightforward request with compile time checking. In this example, I get my associated type autocompletes (‘(firstName: #String#, lastName: #String#)) when typing ‘.createUser…’, so I know exactly what this path needs to make the right request. While that’s a bonus win with Moya, the biggest win for me is, again, the one request interface in ‘MoyaProvider’.

It takes a generic TargetType, which means no more ad hoc api managers. If I want to make a facebook request, all I need to do is declare another ‘TargetType’ conforming enum.

  let facebookProvider = MoyaProvider<Facebook>()
    
    facebookProvider.request(
        .fetchAllFriends(
            facebookId: _String_,
            token: _String_
        )
    ) { (response) in
        // Similar code to handle data/error goes here
        // It's that easy.
    }

…Or Vimeo, or Github, or Stripe, or Mixpanel, or Strava, or really any REST interface with ‘MoyaProvider’.


Granted, there’s no rocket science going on over here. At the end of the day, Moya is just a great networking abstraction actively maintained by many contributers who Moya in production level applications. For those of you who feel that you’ve already solved your networking challenges and are rolling your own better + generic (in a good way) networking layer, kudos to you.

But for those of you like me who’d rather not take on the intellectual challenge to whip up an amazingly flexible and extensible(check the RxSwift Moya extensions) networking library leveraging AlamoFire, using a framework like Moya can greatly free up your mental overhead when programming for iOS because you know more definitively where your network logic lives for each one of your targets.


Watch Connectivity with Core Data in iOS 10

Integrating Core Data with WatchOS

Ever since I bought the apple watch when it first launched last year, I’ve been pretty disappointed with it’s low load times and responsiveness. But it’s now late 2016 and a lot has changed since then. The Apple Watch now operates on WatchOS3, the third installment of the watch’s operating system, and after upgrading my watch, I’ve noticed the watch experience to feel just a bit snappier than before. It’s by no means as fast as how the Watch Series 2 looked in Apple’s demo launch earlier this month, but it works- I’ll take it.

I decided to dabble with the WatchKit framework, while recognizing some new API’s introduced in iOS 10, specifically in Core Data. Up until now, developers would have to write their own core data stack contained in a separate class just to make sense of all that comes with handling managed object contexts. Not anymore. With the new NSPersistentContainer, your managed object model is created and already encapsulated within that class. Creating a mock in-memory persistent store for unit is even easier using NSPersistentContainer.

Putting both WatchOS and Core Data in mind, I explore the ease in which a core data stack can be created, as well as the existing APIs offered on WatchOS for watch connectivity.

This app is really simple- a table view controller with an alert prompt for adding your favorite snacks. The first milestone is syncing this table view onto the watch’s table view. Specifically, whatever is added and deleted from the app’s snack list will propagate to the watch.


Watch and App Communication Design

When creating a watch kit extension, you get two targets: the watchkit app containing UI storyboard files, and the watchkit extension, which houses all the domain logic of our app.

Both the app and the watch need to conform to the watch connectivity delegate in order to pass data between each other. They also need to begin a watchkit “session” before attempting to send data to its counterpart. I could go the easy route and have the application delegate and watchkit extension delegate house the connectivity logic, but that’ll eventually lead to jumbled code in one place. Instead, this app contains two separate classes for delegating connectivity work: PhoneToWatchService and WatchToPhoneService for the app and watch, respectively. There is also a ’Recipe’ object model, our main resource that’s fetched from Core Data.


Midway learnings and tips
  1. Of course, the watch cannot open its parent application if it’s suspended. It needs to at least be in the background for the watch to make any communication with the app.
  2. Unlike the appDelegate in our iOS apps, the ‘rootInterfaceController’ in our watch app is not yet initialized in the watchExtension’s ‘applicationDidFinishLaunching’. I expected the code block below to work the same way we’d inject a dependency to a root view controller dependency in our app delegate.
let rootVC = WKExtension.shared().rootInterfaceController
rootVC.title = "Hello World"

Not true- The root interface controller is actually nil. Based on the documentation,

The root interface controller is located in the app’s main storyboard and has the Main Entry Point object associated with it. WatchKit displays the root interface controller at launch time, although the app can present a different interface controller before the launch sequence finishes.

I’ll look more into the watch extension’s lifecycle, but to me our custom interface controller should be exist ‘at launch time’ in our method ‘applicationDidFinishLaunching’. This poses a problem in our watch connectivity design. I’d like any information passed to the watch to solely be handled by a delegate, ‘IncomingWatchInfoDelegate’. Because I can’t set our rootInterfaceController’s property ‘applicationDidFinishLaunching’, I’ll check for the rootInterfaceController every time a payload arrives from the iOS app, and set our WatchToPhoneService’s delegate to the controller once it exists.


Passing our managed object data to watch

There are several ways you can pass data between watch and app, so I won’t get too much into it as many other blogs discuss each in detail. The point to note is that almost all of the convenient watch connectivity apis relay your information through dictionary key value pairs. In addition, the dictionary can only contain property list types which are basic types such as strings, integers, floats and data. That’s a huge setback if we plan on fetching our recipe managed objects from the app. Fortunately, I have a type alias ‘WatchRecipe’ that is simply a dictionary representation of our Recipe object model. Since our recipe has only one attribute: ‘name’, the mapping from recipe to watch recipe is very straightforward.

let watchRecipes = recipes.map({ (recipe) -> WatchRecipe in
  return ["name": recipe.name as AnyObject]
})

After successfully sending a watch recipe over the transferUserInfo watch API, it’s pretty straightforward from there- we need to take these watch recipe dictionaries and update our watch table view. The watch paradigm is somewhat different from how we traditionally approach and setup our table view’s UITableViewDelegate and UITableViewDatasource methods. For one thing, there aren’t any delegate or datasource methods to conform to in order to present a tableview. You actually set the number of rows and the cell identifier, or “RowType” in one method. Secondly, the table rows are called rowControllers. Instead of cellForRowAtIndexPath, we create our rows all at once.

recipeTableView.setNumberOfRows(recipes.count, withRowType: "RecipeRowType")

for (index, recipe) in recipes.enumerated() {
  let controller = recipeTableView.rowController(at: index) as! RecipeRowController

  if let recipeName = recipe["name"] as? String {
    controller.titleLabel.setText(recipeName)
  }
}

A little different from the conventional cellForRowAtIndexPath jazz, but once you get head around that, you can enjoy your watch table view populated with our app’s snack list!

Deleting snacks

In the next blog post, I’ll explore how to delete rows from both the iOS app and watch, and of course synchronize those changes.

In the next post, I’d like to be able to update my managed objects not just from the app, but from the watch kit extension too. To be clear, I am not attempting to synchronize two data models living in both the app and watch. I am simply passing fetched objects from the app to the watch, and making requests to read, update and delete managed objects from the watch to the app.

I know you can have a data model in the watchOS, but I feel weird about that. In the future, I’m going to test how well persisted managed objects fare in a standalone content on the watch.!

Preventing memory leaks with unowned, weak and capture lists

In many programming languages, memory management is handled with what’s called a garbage collector. With iOS, the rules are a bit different. Apple implements a slightly different method for managing memory in its native app ecosystem called reference counting. Even Swift manages its memory with reference counting since Apple’s libraries are written in Objective-C, forcing Swift to interface with the Objective-C language.

The idea is pretty simple; every object in memory within your application has a count of how many references point to it. When there are no more references, you can effectively deallocate the object in memory since the program does not need it anymore. Sounds simple to manage, but here are three instances where circular referencing typically occur, and what Swift language offers to counter memory leaks

1. Weak references

Say you have an a class named SportsTeam. In this team class, you have an array of type Player.

class SportsTeam {
  var players: [Player]?
}

class Player {
  var team: SportsTeam
}

Now looking into the player class, a player should certainly know what team she/he plays for, so Player will have a field ‘Team’, which references the SportsTeam Class.

In this practical example, you’re going to face a circular reference issue because at the current state, both instances will always reference each other, never allowing their reference count to zero out.

By adding weak to Player’s Team field, you neglect to increment a reference to Team, at least from this instance, and effectively, you break out of a potential memory leak.

class Player {
  weak var team: SportsTeam?
}

class Team {
  var players: [Player] = []

  func addPlayer(newPlayer:Player) {
    players.append(newPlayer)
  }
}

However, there are two caveats to using weak in field declarations.

The first is that the referencing objects have to be independent, meaning they can exist without each other. This relationship between a player and team object is an ideal use case for ‘weak’ because any instance of team can survive without players(empty array), and any player can exist without attributing to a team. That means the team field in Player must be nillable, or in Swift terms, declared as an optional.

In summary, use a weak reference when your object has as independent lifetime and when it’s reference is declared as an optional.

What happens when the lifetime of one object is dependent on its reference?

2. Using unowned references

On the flip side you should use ‘unowned’ when the two referencing objects do not have independent lifetimes. Basically, that mean the objects need each other— so much that it wouldn’t make sense for one to exist without the other.

class Team {
  unowned var createdBy:Player
  init(createdBy: Player) {
    self.createdBy = placedBy
  }

  class Player {
    var Teams: [Team] = []
  }
}

In this example, when Player is destroyed, the reference count in Team will be decremented, and the unowned reference to Player in Team will be ignored by the system.

Nil is not a reasonable value for Team’s unowned ‘placedBy’ reference because it had to be created from somebody! When the lifetime of one object depends on the lifetime of another, use unowned to handle potential circular references.

3. [unowned self] in closures

Background to closures in Swift

There’s one last scenario to keep a eye out for regarding memory leaks, and that’s in closures. Closures are very tricky because they have ‘capture semantics’. By default, they have a strong reference to any variable it uses within its scope. When you reference an instance variable or call a method in swift, you’re implicitly calling self. In a closure however, Swift requires that you explicitly declare self so you are aware self is getting “captured” within the closure block.

Call to method 'netWorthDidChange' in closure requires explicit
'self.' to make capture semantics explicit

You’ll get a compiler error like this within a closure if you ever reference an outer scope variable without explicitly declaring ‘self’. The language wants you understand the possibility of a strong reference cycle in this scenario. Then, how do we solve this strong reference to variables within a closure? The solution is in the power of capture lists.

class Player {
  let firstName: String
  let lastName: String
  init(_ firstName:String, lastName:String) {
    self.firstName = firstName
    self.lastName = lastName
  }

  lazy var greeting:()-> String = { [unowned self] in
  return "Hi, my name is \(self.firstName) \(self.lastName)."
  }
}
let leo = Player("Leo", lastName:"Kwan")
print(leo.greeting())

Take a look at the strange looking array bracket in the ‘greeting’ closure field— [unowned self].

Because closures are objects, we would normally run into another circular reference issue because ‘Player’ references the ‘greeting’ closure while the closure references self. Like I mentioned earlier in the unowned section above, we need to make sure that a referenced object’s lifetime (in this case— a closure’s) is the same as that of Player? We need unowned self again!

This time, however,

it will appear in the form of what’s called a capture list. I don’t fully understand capture lists to expound on them further, but basically, it’s a bracket syntax you add before any parameter clauses in a closure to circumvent circular reference problems. For this example, capture lists allows us weakly reference self, the closure’s creating object, which in turn makes the lifetime of both objects equivalent since the compiler will ignore the closure’s unowned reference count.

Conclusion

So these are three common scenarios to keep in mind while avoiding memory leaks in Swift. I don’t think Apple’s compiler will allow you to access an instance’s reference count. Even if you can, there’s probably many things happening under the hood making additional calls to retain or release. But I suppose it’s more important to recognize where strong reference cycles can exist and what we can do to avoid them!

iOS Design Patterns: Delegation

Knowing what design pattern to implement in your code is one of the most important skills to have as a competent iOS developer.

No, design patterns have nothing to do with user interface or visual design-who would ever think that? -scratch head- Rather, they are reusable solutions that solve common problems, particularly with communication between objects in code.

There are many powerful design patterns found in iOS development. For this blog post, I wanted to expand on the delegate pattern in iOS. Read More

Week 11 & 12 Summary

Week 11

Crunched for time.

There is barely any time to blog during project mode. It’s a long 2 week sprint and our team still has a lot to get done. It’s frustrating because everyone on our team is new to this, but we are learning so much. There is no better way to learn about effective design pattern and features in iOS than devoting 3 weeks time to develop and app that you care about. Time is limited so learning new concepts quickly is not an option. I love the experience, but I can’t wait for this project to be over so that I can reflect on my personal growth here. Read More

Week 9 & 10 at Flatiron School.

Week 9

Traveler App

Week 9 is the start of project mode at the Flatiron School, and that entails developing an app of choice for 3 straight weeks with 3 other classmates. We sort of had a choice with what we are going to make; the deal is each team submits three ideas to our instructors so that they get the final word on what project to pursue. They, of course, have a better handle as to what work is viable and challenging enough for our 3 weeks time.
Read More