Skip to content →

Month: May 2016

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

Modeling State with Associated Enums

Shortly after writing a recent post on enums with associated values, I came upon another use case for such: representing transitory app states.

Here is the scenario. I have an app that goes through an authentication process: attempting to authenticate, successfully authenticated, or failed to authenticate. Similarly, upon authentication, it goes through a second series of steps for data retrieval: requesting and receiving the data, data received, or retrieval failed. Finally, book-ending those two processes, the app has a ready state: either it is or it isn’t ready.

Here’s how I represent these states with associated enum values:

enum AppState {

  case Authentication(OperationState)
  case DataRetrieval(OperationState)
  case Ready(bool)

  enum OperationState {
    case Active
    case Success
    case Failure
  }

  static var state: AppState = .Ready(false)
}

First, AppState captures as case statements the two processes for authentication and data retrieval, and the ready state. The associated value for the processes is the nested OperationState enumeration that captures one of the three states of each of those processes: Active, Success, or Failure. The Ready state need only be represented as true or false. It is the static state property on line 13 that allows me to capture any of those mutually exclusive transitory state values for the app.

Now I can establish that app state and test it like so:

AppState.state = .Authentication(.Active)
AppState.state = .DataRetrieval(.Success)

// ...

switch AppState.state {
case .Authentication(let state):
  switch state {
  case .Active:
    break // stand by
  case .Success:
    break // proceed with data retrieval
  case .Failure:
    break // can't retrieve the data
  }
case .DataRetrieval(let state):
  if state == .Success {
    // refresh the table view
  }
case .Ready(let ready):
  if ready { //...
  }
}

There are two types of comparison here: a switch statement and an if statement. Actually, the if statement on line 17 won’t work out of the box. We first need to conform our AppState to the Equatable protocol (if you’re doing this in a playground, it must go above the AppState definition):

func ==(left: AppState, right: AppState) -> Bool {
  switch (left, right) {
  case (.Authentication(let l), .Authentication(let r)): return l == r
  case (.DataRetrieval(let l), .DataRetrieval(let r)): return l == r
  case (.Ready(let l), .Ready(let r)): return l == r
  default: return false
  }
}

enum AppState: Equatable {
  // The external func ==(left:right:) satisfies Equatable
}

The default case is necessary here because we’re not testing every combination of left and right AppStates; with out it, we’d have to be more explicit, adding these cases:

  case (.Ready, .Authentication): return false
  case (.Ready, .DataRetrieval): return false
  case (.Authentication, .Ready): return false
  case (.Authentication, .DataRetrieval): return false
  case (.DataRetrieval, .Ready): return false
  case (.DataRetrieval, .Authentication): return false

In those instances, we’d in effect be comparing apples and oranges, which are not equal; so we return false. And clearly, having a default return value of false in lieu of all those case statements is preferable.

That’s it! In this illustration I employed associated value enums to represent in a very clean, readable way a series of states that various operations of the app can be in.

In a follow-up post I extend this with a delegate pattern for making notifications when the app’s state changes.

Leave a Comment