Skip to content →

snewolnivekios Posts

Text Field Advancing Protocol

In Keyboard Responsive View Controller, I discussed a demo project that presented a UIViewController extension for automatically moving the active text field into view when obscured by the keyboard. Not discussed there was functionality included in that project for advancing the cursor to the next text field when the user taps the Return key. I discuss it now.

By default, when the user taps the Return key on the iOS keyboard (in this project configured as a Next or Done button), nothing happens. By conforming your UIViewController to the TextFieldAdvancing protocol, your controller gains a text field auto-advance functionality. As a result, when the user taps Return, the focus automatically moves to the next field in the sequence. Optionally, if it’s the last field on the view, it will instead segue to a new scene.

This protocol does require your controller be registered as a delegate of each text field, which is easiest done via the storyboard. Just control-drag from the text field to the view controller button at the top of the scene, and select the “delegate” outlet. You can also do this programmatically with myTextField.delegate = self (this functionality is included in the Keyboard Responsive View Controller extension).

@objc protocol TextFieldAdvancing: UITextFieldDelegate {
  var textFieldSegueIdentifier: String? { get }
}

extension UIViewController {

  /// In response to the user tapping the Return key in a text field, calls upon `advanceFirstResponder(from:)`.
  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    advanceFirstResponder(from: textField)
    return true
  }

  /// Advances first responder to the next text field in the `tag` sequence. For the last text field in the sequence, advances to the next scene via the segue given by `textFieldSegueIdentifier`.
  func advanceFirstResponder(from textField: UITextField) {
    guard let vc = self as? TextFieldAdvancing else { return }
    if let nextTextField = view.viewWithTag(textField.tag + 1) {
      nextTextField.becomeFirstResponder()
    } else {
      if let textFieldSegueIdentifier = vc.textFieldSegueIdentifier {
        performSegue(withIdentifier: textFieldSegueIdentifier, sender: nil)
      }
    }
  }
}

The @objc designation on line 1 is required in order for the Swift protocol’s UITextFieldDelegate method textFieldShouldReturn(_:) to be seen and called by the Objective-C UITextField. Without that, tapping Return has no effect.

Turning to the extension, in a perfect Swift world, this would be a protocol extension, with line 5 reading:

extension TextFieldAdvancing where Self: UIViewController {

However, the UITextFieldDelegate calls are similarly never made.  While it runs, the compiler warns:

Non-@objc method textFieldShouldReturn does not satisfy optional requirement of @objc protocol UITextFieldDelegate.

Matthew Seaman provides a good discussion of this problem, summing up the issue so:

@objc functions may not currently be in protocol extensions. You could create a base class instead, though that’s not an ideal solution.

No, not ideal. Using a base class effectively eliminates the utility of using a protocol in the first place. And because we can’t designate that this extension is of TextFieldAdvancing, we must explicitly test for conformance on line 15.

Let that not detract from the fact, however, that this protocol and extension do work. If you want the user to be able to advance automatically through text fields managed by your view controller, simply conform to TextFieldAdvancing, like so:

class MyViewController: UIViewController, TextFieldAdvancing {
  var textFieldSegueIdentifier: String? = "mySegue"
}

And don’t forget to assign the controller as the delegate of each text field!

Leave a Comment

Keyboard Responsive View Controller

keyboardresponsivedemoHere’s a quick-n-easy UIViewController extension that will make any view with UITextFields on it responsive to the keyboard, moving text fields into view when they would otherwise be obscured by it…without requiring scroll views or other storyboard configurations.

I put this together after implementing the Apple approach using scroll views: Moving Content that is Located Under the Keyboard. I found the overhead associated with reconfiguring my existing project views with scroll views significant and the results inconsistent between views. This approach requires no changes to existing views, and needs but one line of code in your controller to enable the feature (plus a couple “optional” ones).

You will find the Swift 3 demo extension project on GitHub in the extension branch (there’s another branch we’ll get to momentarily).

Note, in the real world you’d do better to implement this particular layout in a UITableViewController; I use it here simply for demonstration purposes. This technique is intended more for content that doesn’t lend itself to a tabular or scrolling view. (Also, for simplicity, I forego the universal layout machinations; this one will look decent on an iPhone 6/7 or 6/7 Plus.)

Here’s the extension.

extension UIViewController {

  /// Returns the text field currently identified as the view's first responder, or `nil` if there is no such first responder.
  func activeTextField(within view: UIView?) -> UITextField? {
    guard let view = view else { return nil }
    if view.isFirstResponder {
      return view as? UITextField
    }
    for view in view.subviews {
      if let activeTextField = activeTextField(within: view) {
        return activeTextField
      }
    }
    return nil
  }


  /// In response to keyboard presentation, animates the active text field into view if obscured by the keyboard.
  func keyboardWillShow(_ notification: NSNotification) {

    // The distance between the bottom of the text field and the top of the keyboard
    let gap: CGFloat = 20

    if let activeTextField = activeTextField(within: view),
      let keyboardFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {

      // Calculate delta between upper boundary of keyboard and lower boundary of text field
      let textFieldFrame = activeTextField.superview!.convert(activeTextField.frame, to: view)
      let textFieldBound = textFieldFrame.origin.y + textFieldFrame.size.height + gap
      let keyboardBound = keyboardFrame.origin.y
      let viewShift = min(keyboardBound - textFieldBound, 0) // Don't shift if keyboard doesn't cross text field boundary

      // Shift the view
      var viewFrame = view.frame
      viewFrame.origin.y += viewShift - viewFrame.origin.y // Account for previous shift
      UIView.animate(withDuration: 0.5) {
        self.view.frame = viewFrame
      }
    }
  }

  /// In response to keyboard dismissal, animates the view back to its original position.
  func keyboardWillHide(_ notification: NSNotification) {
    var vwFrame = view.frame
    vwFrame.origin.y = 0
    UIView.animate(withDuration: 0.5) {
      self.view.frame = vwFrame
    }
  }

  /// Enables keyboard responsiveness to text fields, animating the view such that the currently active text field is not obscured by the keyboard. Call this method from `viewDidAppear(_:)`.
  func activateKeyboardResponsiveTextFields() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }

  /// Disables keyboard responsiveness to text fields. Call this method from `viewWillDisappear()`.
  func deactivateKeyboardResponsiveTextFields() {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }
}

The view controllers you wish to take advantage of this behavior need to call upon those last two methods, as follows:

override func viewDidAppear(_ animated: Bool) {
  activateKeyboardResponsiveTextFields()
}

override func viewWillDisappear(_ animated: Bool) {
  view.endEditing(true)
  deactivateKeyboardResponsiveTextFields()
}

The call to endEditing() on line 6 is not strictly necessary, but I found overcame some less-than-premium keyboard presentation behavior when unwinding to a controller that had previously segued with the keyboard visible.

Note that in the extension itself, beginning on line 4, we cannot obtain the activeTextField the same way Apple does in their example code, that is, by using the UITextFieldDelegate methods textFieldDidBeginEditing(_:) and textFieldDidEndEditing(_:). This is because they use a stored property to capture the active field. Thus the extension must find it programmatically by recursively traversing the view’s subviews, looking for the one that isFirstResponder.

This activeTextField(within:) method is called once each time the keyboard shows, which actually happens each time a field becomes the first responder, such as when the focus moves from one text field to the next, even if the keyboard is already present. This process happens so quickly within the run loop, however (even with this activeTextField(within:) traversal), that the keyboard doesn’t actually dismiss and reappear.

Where could you go from here?

While this extension is arguably Swifty and lightweight, there is some overhead we carry into each view controller taking advantage of it. We can eliminate that overhead by converting the extension into a subclass of UIViewController. While perhaps non-Swifty (classes are so heavyyy), it does have these benefits:

  • Replaces what amounts to a computed activeTextField property with a stored property (however negligible that processing requirement may be).
  • Eliminates the explicit calls to (de) activateKeyboardResponsiveTextFields(). Instead, one must only subclass KeyboardResponsiveViewController.

Take a look at the subclass branch of the repo for this implementation.

Leave a Comment

Recalibrate: Sprint Velocity or Story Points?

If you’re pushing ahead full throttle toward a project deadline and see your project buckling at the seams, what do you do? Keep going and pick up the pieces sometime after the deadline, or throttle back? If the latter, what does that look like?

Recalibrate What?

That topic of throttling back came up in a recent discussion with our team’s product owner, and it quickly became clear there were two different perspectives among us: recalibrate our planned sprint velocity (reduce it) or recalibrate our planned story points (inflate them). As to why the latter option was under consideration, it’s useful to have a little background.

The Situation

We are a relatively new (and for some members, young) team on a new project working since February at about 40 points per 4-week sprint toward a somewhat firm (but widely advertised) 6-month Initial Operational Capability (IOC) release date.

There’s been a healthy backlog of features planned for this initial release, and the customer’s emphasis in order to accomplish them has for the most part been function over form (with an upon-delivery desire for both, of course).

What’s more, us developers yielding to our own desire to deliver functionality quickly, we have not given the attention to our Definition of Done it deserves. While well intentioned and far from ignoring it, we have made some sacrifices in the areas of architecture & design, documentation (architecture, API, and inline), unit testing, and what we have recently dubbed a “premium user experience” (all of which I herein characterize as “form”).

(Another factor is the nature of iterative development. We don’t know or are directed to defer consideration of future requirements in the interest of achieving today’s requirements. But that’s a topic for another day.)

What do story points represent?

So back to the question at hand: Does this conflict between function and form mean we need to slow our velocity or inflate our story points? To achieve the desired function and form, the Inflate proponents see a need for more story points. The Velocity folks see a need for more work per story point. Which begs the question…what do story points represent?

Before I answer that, I’ll add—being a CMMI Maturity Level 5 organization—we also have a bit of process integrated into our workflow. Not detracting from its virtue, it does increase the amount of work required to complete a story. Importantly, however, I have found this process to be roughly proportional to the complexity of the task. And the same is true for form.

Frankly, as a developer, I find it easier when sizing a story to think only in terms of the story’s complexity: “How hard is it going to be to do this?” I am able to estimate my own technical capability and that of my teammates, to evaluate the technical challenges of and external constraints on the task, and so on.

Things get fuzzier, though, when simultaneously I try to consider form and process…short of just using a multiplier. But here’s the problem with multipliers: they don’t fit well with a Fibonacci sequence sizing paradigm. What’s more, if you’re applying the same multiplier to each story, why bother? If you’re not, is the multiplier you choose from story to story something other than arbitrary? Too much to think about!

Do away with the sizing complexity and focus on function complexity. There’s no need also to consider form and process; they come along in proportion.

Recalibrate This

With the clarity gained by focusing on function complexity without consideration for form and process, I’m a proponent of throttling back on velocity and an opponent of inflating story points. You need more time to ensure a “premium” developer and user experience? Take it. But keep the story points that measure function complexity the same, being sure to give form the attention it’s due.

Leave a Comment

Delayed Preemptive Dispatch

DelayedPreemptiveDispatchQueueDemoIf you’re looking to run a task closure concurrently using Grand Central Dispatch after some delay … with the option to delay it again, replace it with another task, or cancel it altogether, the concept of delayed preemptive dispatch presented here may be of interest to you. For a quick peek, skip to Implementation; for use cases, read on.

Problem Scenarios

Consider these problem scenarios, all taken from some of my recent work. How would you implement the described functionality?

  1. You want to allow a user to make three incorrect passcode entries within a minute of each other before locking them out. If more than a minute elapses between entries, the try count resets to zero.
  2. You are using a third party framework that presents a panning view. Its API provides the means for notification as each pan motion stops…both when the pan comes to a rest and when the user interrupts one pan motion to start another. However, you need to know when all panning has stopped.
  3. You are interfacing with a third party library that concurrently retrieves an unknown quantity of online resources on your behalf. It only notifies you as each resource is downloaded. However, you need to take some action once all resources have loaded.

My approach to these problems was a common one: use a system I call  delayed preemptive dispatch (the term “dispatch” coming from Apple’s Grand Central Dispatch (GCD) libdispatch library available on all their operating systems from the Watch to the TV).

The gist of this system is I want to perform a task after a brief delay, but only if I don’t preempt it with another task before the prior task’s timer expires (in effect canceling the prior one); it is at the conclusion of the last submitted delay that the last submitted task is executed.

Here’s how I apply this to the above three problems, identified by the event I wish to be notified of:

  1. Invalid passcode expired. I start a one-minute timer when a passcode has been wrongly entered that, upon expiration, runs a task to reset the entry count. However, I don’t want that closure to run if, in the meantime, the user has re-entered the passcode. Instead, I want to preempt the first closure, replacing it with a second one-minute timer that will itself reset the entry count. Importantly, once the user enters the passcode correctly, I want to cancel the task altogether.
  2. Panning stopped. Here I start a timer upon receipt of a pan-stopped notification that, upon expiration, declares all-stop on panning. However, I don’t want that to occur if a subsequent pan-stop event occurs in the meantime. Rather, I want to preempt the preceding closure with the next and, yes, initiate a new delayed notification closure.
  3. All resources loaded. Finally, in this case I start a brief timer after each resource loads that, upon expiration, signals all resources loaded. However, I don’t want that signal to fire if a subsequent resource loads before the timer expires. Instead, I want to preempt the preceding notification closure and replace it with another one that, if not itself preempted, will be the one to notify all resources have been loaded.

Implementation

At this GitHub repo you will find an implementation of what I call a DelayedPreemptiveDispatchQueue, written in Swift 3, which includes unit tests and the above-illustrated UI demo.

With this class you can delay execution of a task until expiration of a timer, with the option to later reset the timer, preempt the task with another, or cancel the task altogether. It makes use of the Swift 3 GCD DispatchGroup to manage concurrent timers and fire off the delayed task once all the timers have expired.

Here’s a peek at the delay(_:task:) method in that class (see the repo for the full source):

/// Executes `task` no earlier than after the given delay. 
///
/// Subsequent calls to this method will preempt execution of this `task`. The task may also be provided via the class initializer. Cancel execution of a task via `cancel()`.
///
/// - parameter seconds: The number of seconds before this or the initializer-givn task may be executed. The delay will be longer if there is a pending delay that expires after this period.
/// - parameter task: The closure to run after _all_ pending delays have expired. If `nil` (the default), the task to be run is that given at initialization. If no task was given during initialization or at any call to this method, it takes no action.
func delay(_ seconds: TimeInterval, task: (() -> Void)? = nil) {

  // Make sure we have a defined task task
  if task != nil {
    self.task = task
  }
  guard self.task != nil else { return }

  // Newly submitted task preempts prior cancellation
  cancelled = false

  // Add delay timer to the dispatch group
  group.enter()
  self.queue.asyncAfter(deadline: DispatchTime.now() + seconds) {
    self.group.leave()
  }

  // Only assign GCD notify action when first timer added to group.
  // The notify action, which performs the task, runs once all timers have left the group.
  if empty {
    self.empty = false
    group.notify(queue: .main) {
      if !self.cancelled {
        self.task()
      }
      self.empty = true
    }
  }
}

The task may be provided via init(label:task:) (not shown), delay(_:task:), or a combination of both. Neither the delay times nor tasks need be the same with each call. Only the last task submitted will be called once all concurrent delay timers have expired. While you cannot cancel the timers themselves, you can cancel execution of the task via cancel() (also not shown). Once all timers have expired, you can reuse the DelayedPreemptiveDispatchQueue with or without specifying a new task.

While this class makes use of the DispatchGroup to manage a group of timers, the functionality given by DelayedPreemptiveDispatchQueue is not inherent to it. For example, you cannot provide a task to a DispatchGroup at initialization, but only via its instance notify() method. Also, all tasks submitted to a dispatch group execute; there is no concept of “preemption” as there is in this class.

For documentation on the Swift 3 implementation of Grand Central Dispatch, reference this current pre-release Swift 3 evolution proposal 88, “Modernize libdispatch for Swift 3 naming conventions.”

Leave a Comment

Page View Controller in a Container View

Late one evening this week I decided to turn Netflix off and see what I could cobble together with regard to a feature a teammate of mine was working on, namely, using UIPageViewController to provide paginated content.

PageViewControllerDemoAs seen in the animation, for us there are some key characteristics of the targeted implementation. These include:

Swift 3 language and UIKit features illustrated but not specifically discussed include:

  • Protocols
  • Switch case value bindings akin to if let value = value as? SomeType
  • String splitting using map(); substrings
  • UITableViewController and UITableViewControllerDataSource
  • Storyboard and programmatic instantiation of view controllers
  • UIView.animate(withDuration:animations:)

If any of these topics interest you and you want a quick fix, take a look at the project on GitHub, written in Swift 3 (updated for Swift 4). Have specific questions? Keep reading.

FAQ

  • How do I provide paginated content? There’s a storyboard piece and a programmatic piece. In summary, on the storyboard you drop in and hook up a Page View Controller object into your scene flow and add a content object of your choosing. Programmatically, you need only implement a couple UIPageViewControllerDataSource methods … and provide the initial view controller. See PageViewController.swift for that implementation. Details below.
  • How do I use a page scroll rather than curl transition? In the Attributes Inspector for the Page View Controller storyboard scene, set “Transition Style” to “Scroll”.
  • How do I add a page indicator? Implement UIPageViewControllerDataSource methods presentationCount(for:) and presentationIndex(for:); see PageViewController.swift. If you don’t want a page indicator, don’t implement these methods.
  • How do I set the color of the page indicator dots? See PageViewController viewDidLoad():
    let pageControl = UIPageControl.appearance(whenContainedInInstancesOf: [PageViewController.self])
    pageControl.pageIndicatorTintColor = .lightGray
    pageControl.currentPageIndicatorTintColor = .black
    
  • How do I embed a paginated subview? The storyboard is all you need. The process I follow:
    1. Drop a Container View onto the containing view. If you’re good with the tag-along view controller, stop here.
    2. Otherwise, delete the tag-along view controller.
    3. Add the desired controller to the storyboard.
    4. Control-drag from the container to the controller.
    5. Select the “Embed” segue.
  • How do I use a segmented control to switch between subviews? My approach is through manipulation of each subview’s hidden property, accessed by @IBOutlet connection. See MainViewController.swift.
  • How do I reuse a view controller in a storyboard? I recommend embedded Container Views (they’re awesome!). In this project, I have one container view with an Embed segue directly to the content table view controller; then I have a second container view with an Embed segue to the Page View Controller that is programmatically connected to the same table view controller.
  • How do I access a container-embedded view controller? Rather simply…when you know how. The trick is to override prepare(for:sender:) in your container view controller. By doing so, you get access to the destination (embedded) view controller via the provided UIStoryboardSegue. See MainViewController.swift.

Details

Okay, let’s dive into some details. Keep in mind the context of this discussion is the specific implementation as given on GitHub.

Storyboard

Assuming you know the basics of Interface Builder storyboarding, here are some things to be aware of:

  • There are two container views on the project storyboard; although, because they’re stacked, you only see one. The first, named “Paged Container View”, has an embed segue to the Page View Controller scene. The second, “Unpaged Container View”, has an embed segue to Table View Controller.
  • Table View Controller has a Storyboard ID of “TableViewController”, which PageViewController makes use of when serving up paged view controllers.
  • There is no direct connection between Page View Controller and Table View Controller on the storyboard. As just alluded to, that is done programmatically in PageViewController.
  • The Table View Controller has one basic prototype cell matched with a class defined in TableViewController.swift named BasicCell.

Page View Controller

The back end of the Page View Controller storyboard scene is a UIPageViewController-subclassed PageViewController that conforms to the UIPageViewControllerDataSource protocol, much the way UITableViewController now does inherently for its data source and delegate.

At a minimum, a UIPageViewController needs only two things to get paging working:

  1. The plugged-in viewControllerAfter and viewControllerBefore data source methods.
  2. The initial view controller (or view controllers if you’re presenting two pages at at time).

Our page content is presented by a TableViewController. Rather than pre-populating a collection of controllers for all pages, I serve them up on-demand one at a time.

PageViewController maintains no state of its own as concerns which page we’re currently viewing. We leave that to each TableViewController via its section property. In viewDidLoad() we initialize the first Table View Controller’s section to zero, and the page view controller’s data source methods take it from there.

When UIPageViewController asks its data source for the previous or next page, we query the current view controller’s section value to do some bounds checking and initialize the new controller. If within bounds, we return the new controller; otherwise, we return nil.

Table View Controller

The reusability of this controller in two contexts hinges entirely on the optional section property:

  • When non-nil, as set only by the PageViewController, we can know the data is paginated and should only serve up one section, which one being determined by this section value.
  • When nil (i.e., left in its initial state), we know the controller is being used by the directly embedded container view, and needs to serve up data for all sections.

Functionally, this TableViewController is entirely a UITableViewDataSource, providing the bare minimum number of sections, rows per section, section title (not necessary, but useful), and cells. It calls upon an abstracted BasicTableDataModel for those values. This model is assigned by the PageViewController, which it receives from the MainViewController.

Anytime these methods reference the section, they use the sweet nil-coalescing operator to give priority to the optional section property, and failing that, the parameterized section or indexPath value.

Page Indicator

Actually managed within the PageViewController, the page indicator is made possible by implementing two additional UIPageViewControllerDataSource methods: presentationCount(for:) and presentationIndex(for:).

They’re straightforward enough. The only oddity is presentationIndex(for:) is called after viewControllers is initialized to an empty array, but before it is populated. Thus the reason for the nil and count > 0 checks.

Customization of the indicator, that is, its color, is another peculiarity. UIPageControl utilizes an “appearance proxy”, which implements the UIAppearance protocol.

For this project, it comes down to the three lines of code from viewDidLoad(), as given earlier and repeated here:

let pageControl = UIPageControl.appearance(whenContainedInInstancesOf: [PageViewController.self])
pageControl.pageIndicatorTintColor = .lightGray
pageControl.currentPageIndicatorTintColor = .black

If you were only to have one page indicator across your app or want them all to have the same colors, you can replace the first line with:

let pageControl = UIPageControl.appearance()

And, if follows, you can do that anywhere, such as in the AppDelegate.

Basic Table Data Model Protocol

An update to my original implementation addresses my glossing over how model data might work its way into the table view in the real world.

In this update, I add a BasicTableDataModel protocol and two conforming types (LatinTableDataModel and NumericTableDataModel) that present distinct data for use in the paged and non-paged views.

The MainViewController is now the keeper of the models, passing them down to the container view controllers via the segue method prepare(for:sender:). The PageViewController then passes its assigned model down to the individual TableViewControllers it instantiates.

Wrap Up

Adding a page view controller to your project is as simple as:

  1. Dropping a Page View Controller into your storyboard
  2. Connecting to a UIPageViewController-derived class that implements its data source protocol
  3. Employing an approach for serving up paged view controllers that fits with your use case, which really just comes down to providing a view controller with the page-specific model data it needs to display
  4. Optionally, configuring the page indicator by implementing a couple more data source methods and customizing it to a color suitable for your view.

By way of bonus material, you also got to see how to:

  • Reuse and tailor model data for a single view controller in multiple contexts
  • Use a segmented control to switch view contexts within a single controller.

Good stuff. Now, back to Netflix…

10 Comments

extension Queue: SequenceType

Previously, I presented a linked-list-based Queue class in the context of a discussion around Automatic Reference Counting (ARC). Here I extend that class to conform to the SequenceType protocol, and then add some bonus initializers that mirror those given for Swift’s collections.

In simplest terms, it is the SequenceType protocol that allows us to iterate over the elements in the Queue:

for element in queue {
  // do something with element
}

But that’s just the beginning. Taking a look at the Appe documentation and this excellent post by Nate Cook on the Swift Collection Protocols, we find that because of this iterability, we gain significant functionality for free, a subset of which includes the likes of enumerate, map–filter–reduce, reverse, sort, and so on. Good stuff!

Now, a SequenceType makes no guarantees as to whether the sequence is consumed, so if we were interested only in iteration and didn’t care about that (or perhaps wanted it to be consumed), we could destructively iterate like so:

while let element = queue.dequeue() {
  // do something with element
}

However, our Queue is constructed in such a way that it need not be consumed on iteration.

Generator

So let’s give Queue an iterator (generator in Swift vernacular) and declare its conformance to the SequenceType protocol. There’s not much to it, at least as far as Queue is concerned:

extension Queue: SequenceType {

  /**
   Returns a `SequenceType` generator for iterating over the queue.
   */
  func generate() -> QueueGenerator<T> {
    return QueueGenerator(queue: self)
  }
}

Beyond that, we need only define the QueueGenerator returned by generate(). It takes our Queue object and, with its front property and each node’s next property, non-destructively iterates over the elements in the queue:

/**
 The generator by which `Queue` conforms to `SequenceType`.
 */
struct QueueGenerator<T>: GeneratorType {
  
  /// The queue being iterated over.
  var queue: Queue<T>
  
  /// The current node.
  var node: QueueNode<T>?
  
  /**
   Initializes iteration at the front of the given `queue`.
   */
  init(queue: Queue<T>) {
    self.queue = queue
    node = queue.front
  }
  
  /**
   Returns the next element in the queue, or `nil` if the queue is empty or all nodes have been iterated.
   */
  mutating func next() -> T? {
    let element = node?.element
    node = node?.next
    return element
  }
}

Notice that like the previously defined dequeue() method, the next() method is not returning a queue node, but rather the element of type T that is wrapped by the node.

And that’s all there is to for SequenceType conformance!

Initializers

But before we move on, let’s go back to our original Queue definition and drop in some initializers that allow Queue construction to work like Swift’s own Array and Set types:

class Queue<T>: SequenceType, ArrayLiteralConvertible { // continued

  /**
   Construct an empty queue.
   */
  init() { }
  
  /**
   Construct an instance containing `elements`.
   */
  required init(arrayLiteral elements: T...) {
    for element in elements {
      enqueue(element)
    }
  }
  
  /**
   Construct an instance from an arbitrary sequence with elements of type `Element`.
   */
  init<S: SequenceType where S.Generator.Element == T>(_ sequence: S) {
    for element in sequence {
      enqueue(element)
    }
  }
}

The first constructor was implied by the previous omission of any initializers, but now that we’ve added the other two, we must explicitly define it. However, because Queue consists only of optional properties, they are automatically initialized to nil. Since this is the “default” state, there is nothing for it to initialize.

The second initializer uses the Swift ellipses syntax to indicate a comma-separated list of literal values, which it converts into an Array. This is all that’s needed for ArrayLiteralConvertible protocol conformance, so I add that to the class. This in turn necessitates the use of the required modifier on the initializer, as the initializer is required by the protocol.

Finally, the third initializer allows us to build a queue from any SequenceType, such as an Array, Set or Dictionary. The syntax used here is that of the generic parameter clause, which adds a constraint to the Queue‘s generic argument T. That constraint says S conforms to the SequenceType protocol and the associated type S.Generator.Element is of type T. In other words, we can pass in any sequence of type T elements.

Here’s what those initializers look like in application.

let array = [3, 7, 2, 9]
let set = Set(arrayLiteral: 3, 7, 2, 9)
let dict = ["A": 3, "B": 7, "C": 2, "D": 9]
let queue1 = Queue<Int>()
let queue2 = Queue(arrayLiteral: 3, 7, 2, 9)
let queue3 = Queue(array)
let queue4 = Queue(set)
let queue5 = Queue(dict.values)
let queue6 = Queue(queue2)

Some points of note:

  • We’re able to drop the <Int> type specification on any but the first initializer, thanks to Swift’s type inference.
  • We can now initialize one Queue with another.
  • Only the Queue and Array types maintain their order as initialized, so the arrangement of the elements for queue4 and queue5 are not necessarily 3, 7, 2 and 9.
Leave a Comment

A Generic Swift Queue and ARC

In my current project, I set off to implement a generic queue in Swift, and settled on the use of a linked list for doing so, where my queue is a collection of singly linked nodes. As it turned out, this ended up being fertile ground for illustrating Swift’s use of Automatic Reference Counting (ARC) for memory management, something I take on in this post.

For the visual learners, here is an illustration to assist the discussion, courtesy of Paper by 53 and my iPad Pro (with Apple Pencil, of course):

IMG_0040

The top row represents three people waiting in line at Walmart customer service (who hasn’t been there?). The second row shows the first person has been helped (dequeued), leaving two. And the third row shows two new customers have arrived (enqueued), eager to make their returns, before anyone else has been helped. The orange numbers correspond to reference counts (more on that in a moment).

Queue Node

So to begin, let’s take a look at the building block of the queue, the node (represented by the circles in the diagram):

/**
 The component of a queue that provides the queue's content and sequence.
 */
class QueueNode<T> {

  /// The data element stored in the queue.
  var element: T

  /// The node that is "next in line", or `nil` if there is no subsequent node.
  var next: QueueNode?

  /**
   Wraps the given `element` into a node, leaving `next` set to `nil`.
   */
  init(element: T) {
    self.element = element
  }
}

Being part of a linked list, it is necessary for the node to be a class, as linked lists rely on reference pointers, and only Swift classes—as reference types—can be “pointed” to. (In contrast, any assignment of a structure or enumeration stores a copy of the object in the receiving variable, property, or parameter.)

Queue

Next, let’s begin taking a look at the class that takes the QueueNode building block and with it forms a fully functional Queue data structure:

/**
 A generic collection that provides standard enqueueing and dequeuing functionality.
 As elements are enqueued, they are conceptually added to "the back of the line;" 
 as they are dequeued, they are removed from "the front of the line." 
 */
class Queue<T> {

  /// The first enqueued node or that following the last dequeued node.
  private var front: QueueNode<T>?

  /// The last enqueued node.
  private var back: QueueNode<T>?

  /// The number of elements in the queue.
  private(set) var count = 0
  
  /// True if there are no elements in the queue, false otherwise.
  var isEmpty: Bool {
    return count == 0
  }
 

I want to interrupt here to point out that the class properties front and back defined on lines 9 and 12 are effectively pointers, as is the function variable node on line 28 below (reference the diagram).

  /**
   Adds the given `element` to the back of the queue.
    - complexity: O(1)
   */
  func enqueue(element: T) {
    
    let node = QueueNode<T>(element: element)
    
    // First node
    if front == nil {
      front = node
      back = node
    }
      
    // Subsequent nodes
    else {
      back!.next = node
      back = node
    }

    count += 1
  }
 

It is on line 28 that this class allocates memory for, creates, initializes and assigns a reference to a new QueueNode object (all done behind the scenes by Swift). In accordance with ARC, as long as this object has a property, variable or parameter pointing to it, it will remain allocated. This node is short-lived, though, so the only potential direct references held by Queue are front and back. It is the nodes themselves that maintain the next references keeping the chain of nodes alive (again, the diagram).

  /**
   Removes and returns the element at the front of the queue.
   - complexity: O(1)
   */
  func dequeue() -> T? {
     
    // Queue is empty
    if front == nil { return nil }
     
    // Remove first node/element
    let element = front!.element
    front = front!.next
     
    // Deallocate dequeued back node
    if front == nil {
      back = nil
    }
 
    count -= 1
     
    return element
  }
 

Consider line 56 in dequeue(), where front is reassigned to the object pointed to by its own next property. This leaves the node formerly known as first with nothing referring to it, triggering implicit and immediate deallocation; there’s no need to explicitly deallocate it, such as with a nil assignment.

In contrast, if we have dequeued the last node, we need to explicitly release it by reassigning back to nil (line 60), otherwise back will retain that node until the queue itself is deallocated (at which time it is automatically set to nil).

Automatic Queue Deallocation

In the context of queue deallocation, such as when the reference count for a Queue object drops to zero, front is assigned to nil. When that happens the associated node’s reference count also drops to zero, triggering its deallocation. This causes the setting of the node’s next property to nil, which then decrements its adjacent node’s reference count to zero, thereby triggering that node’s deallocation, and so on. This chain reaction continues until the last node in the linked list is reached.

As discussed in the context of dequeue(), this last node is also pointed to by the queue’s back property, thus preventing its reference count from dropping to zero, and thereby keeping the object alive. It is not until back is set to nil (line 60 above) that the reference count drops to zero and the last node is deallocated.

The process of deallocating the nodes between front and back happens automatically courtesy of ARC memory management built into Swift and Objective-C. You can see it in action by using this script and addition to QueueNode:

class QueueNode<T> { // continued
  deinit {
    print("\(#function)")
  }
}

func testQueue {
  let n = 10
  var queue = Queue<Int>()
  for i in 1...n {
    queue.enqueue(i)
  }
}
testQueue()
print("done")

Once testQueue() exits, you’ll see its queue variable is automatically deallocated as described, which in this case would result in 10 debugger console output lines that read “deinit” before “done” appears.

Large Queues

Now you might find that for large queues, trouble ensues in the form of a EXC_BAD_ACCESS runtime error. I found taking the reigns on deallocating the individual QueueNodes ensured the deallocation of any sized queue works flawlessly.

Returning to our Queue definition, this is a simple matter of adding a deinit method that calls upon a removeAll() method familiar to users of Swift’s collection types:

  /**
   Explicitly deinitializes all enqueued nodes.
   - complexity: O(n)
   */
  deinit {
    removeAll()
  }

  /**
   Removes all elements from the queue.
   - complexity: O(n)
   */
  func removeAll() {
    while front != nil {
      front = front!.next
    }
    back = nil
    count = 0
  }
}

Note we haven’t completely given up on ARC. As it did in line 56 previously, the same implicit deallocation occurs here on line 82: as soon as the front = front!.next assignment is made, the node that was the front node is deallocated. Where we short-circuit the automatic chain-reaction deallocation discussed above is in that front reassignment. Were we to replace lines 81–83 with a simple front = nil, we would be back to the default behavior we had without a deinit method.

And yes, for you lines-of-code hounds out there, I could have written removeAll() as a simple one-liner with the loop while dequeue() != nil { }. I contend, though, the given approach is superior for performance reasons, however negligible. There’s a bit more overhead in calling dequeue() 100 million times, let’s say, than in dereferencing that many nodes directly (in a single test, this amounted to 45 versus 65 seconds…a near 150% increase).

More to Come

That does it for now. In my next post I conform the Queue to SequenceType so it can be iterated with the likes of:

for element in queue {
  // do something with element
}
Leave a Comment

RIP++

When I recently had occasion to “prepare” for Swift 3.0 a third-party library our team is using, it struck me just how useful the C-based post-increment (and decrement) operator is. Consider this simple Swift 2.2 line from that library:

return (String(self.arrayIndex++), JSON(o))

To those not familiar with this post-increment unary operator, the arrayIndex doesn’t get incremented until after it is converted to a String. With the loss of that operator in Swift 3.0, this one-liner grows to this:

let arrayIndexString = String(self.arrayIndex)
self.arrayIndex += 1
return (arrayIndexString, JSON(o))

Can’t say I agree with the stated “disadvantages” of this operator, which appear to focus on a very simplistic use-case that contrasts x += 1 and x++. Sure, in that case, there’s no added utility. And hard to learn? I’ve seen that argument repeated in other “do away with this” arguments; hog wash. Swift contains much more complicated constructs than a post-increment operator!

Alas, I’m a bit late to the party, and the fate of ++ has already been sealed. Thankfully, it’s not “goodbye,” but just “see you later”…when I return to the likes of C++.

Leave a Comment

Naming Interface Builder Outlets and Actions

Ever wondered how to name an @IBOutlet property or @IBAction method and felt conflicted over “the right way to do it”? You’re not alone:

In case that’s you, here’s the Apple-sanctioned convention:

  • For @IBOutlets, the property name comes in two parts. First, begin with a description of the contents of the control, such as username, passcode, or authenticationNotification. Then add the name of the control, such as Label, TextField, and Button. The result: usernameLabel, usernameTextField, and passcodeButtons. Examples of what not to do: trustAgentUsername: UITextField and authenticationNotification: UILabel.
  • For @IBActions, the method name simply describes the action; there is no control name suffix as with an @IBOutlet. For example, a UIButton action that capitalizes a word in an associated UITextField would be properly declared func capitalizeWord(sender: UIButton). An action that removes a user would be func removeUser(sender: UIButton). Examples of what not to do: didTapButtontappedDone, or overlayTap.

Specific Apple resources prescribing and modeling this convention include their “Start Developing iOS Apps (Swift)” guide, specifically Lesson 3, “Connecting the UI to Code“, and their discussion on Target-Action in the “Concepts in Objective-C Programming” documentation. Their Swift API Design Guidelines say nothing on the matter, presumably deferring to their elsewhere-stated conventions.

A corroborating resource I found is Matt Thompson’s “IB Outlet / IB Action / IB Collection” article. RayWenderlich.com, while also corroborating, has little to say on this specific issue, giving but one example (out of this particular context, even) of an @IBAction between their Objective-C and Swift style guides.

If you have found yourself asking, “How do I name my IB connections?”, hopefully this clears things up for you. It’s not complicated; it’s just a matter of knowing.

Leave a Comment

App State-Change Notifications to Multiple Delegates

In a prior post on Modeling State with Associated Enums, I set up a mechanism for capturing and querying an app’s state, as follows:

AppState.state = .Authentication(.Active)
AppState.state = .DataRetrieval(.Success)
// ...
if AppState.state == .DataRetrieval(.Success) {
  // ...
}

In this post I use the delegate pattern to add state observation by any component of the app that needs to respond to state changes. I begin by defining the delegate protocol:

/**
 An `AppStateDelegate` receives notification when the application's state changes.
 */
protocol AppStateDelegate {

  /// Called when the app state has changed.
  func appStateChanged(state: AppState)

  /// Uniquely identifies the delegate.
  var hashValue: Int { get }
}

The appStateChanged(_:) method will be called any time the state changes (makes sense!). But what about that hashValue on line 11? When it comes to delegates, this is an instance where it is appropriate and, perhaps, necessary to register multiple delegates: there are likely to be multiple places across the app where I need to know about state changes. The hashValue is going to help with that…

My approach for supporting multiple delegates without using NSNotificationCenter is to add to the previously defined AppState enumeration a dictionary of delegates:

enum AppState: Equatable { // excerpt

  /// Delegates registered for `appStateChanged(_:)` notifications.
  private static var delegates = [Int: AppStateDelegate]()
}

(Before getting to the dictionary, note I have chosen to make this and future declarations static. I have done so because, not unreasonably, the state of the app applies to the entire app, and there is only one instance of the app running at a time.)

It is to this AppStateDelegate dictionary that notifications will be made. I have chosen a dictionary here as a meet-me-halfway point between an array and a set. A set would be ideal, but it requires the delegate to conform to the Hashable protocol, something not as easy as it seems, and that I leave for a future exercise. In the meantime, we’ll use the dictionary so as to prevent registration of duplicate delegates.

Delegate registration occurs via the delegate property setter, defined next:

enum AppState: Equatable { // excerpt

  /// Registers the `delegate` with `AppState`.
  /// All delegates are notified upon assignment to `state`. 
  static func addDelegate(delegate: AppStateDelegate) {
    delegates[newValue.hashValue] = newValue
  }
}

The addDelegate(_:) method simply adds the given delegate to the dictionary, relying on the default no-duplicate-keys functionality that comes with a dictionary to ensure no delegate is registered more than once.

A delegate property could be used in lieu of this method, using the setter to make this same dictionary addition, but doing so actually adds a level of unneeded complexity given we’re using multiple delegates: which delegate should the getter return? Using a method avoids that peculiarity.

The dictionary is keyed on the protocol’s hashValue integer. The expectation is any registering delegate itself already conforms to the Hashable protocol (without explicitly requiring such conformance), and thereby has a fitting hashValue implementation that will ensure the uniqueness of the key. If it doesn’t conform, the AppStateDelegate protocol requires a hashValue anyway, so I call it good for now.

With delegates registered, notification is triggered by the following didSet block:

enum AppState: Equatable { // excerpt

  /// The current state of the app. 
  /// Any assigned `AppStateDelegate`s are notified on assignment.
  static var state: AppState = .Ready(false) {
    didSet {
      for delegate in delegates.values {
        delegate.appStateChanged(state)
      }
    }
  }
}

The process of notification is quite simple: call appStateChanged(_:) on each of the delegates in the dictionary. (Note, as explained by the Swift Programming Language Guide, didSet is not called when the value is first initialized.)

Putting all that to use, here is a sample listener implementation that shows registering as a delegate for and receiving app state-change notifications.

import UIKit

class SomeViewController: UIViewController, AppStateDelegate {

  override func viewDidLoad() {
    AppState.delegate = self
  }

  func appStateChanged(state: AppState) {
    if state == .DataRetrieval(.Success) {
      // do something...
    }
  }
}

Note that because a UIViewController already conforms to the Hashable protocol, there is no need to explicitly provide a hashValue implementation. The result? Each time AppState.state is updated, this controller and any other registered delegates are notified via the protocol’s appStateChanged(_:) method.

Leave a Comment