Blog

Benchmarking Xcode Builds

I recently started working with a fairly large iOS/Swift code base — one which takes several minutes to complete a full build from a clean folder. Since I have several macOS workstations on-hand, I naturally was curious how they compare in my most common use case — developing Swift iOS applications. Is there one that would give me less time to fetch a cup of coffee during a full build?

The code base

The code base I’m working with for these tests has the following profile:

Swift files: 223

Objective-C files: 6

Storyboards: 35

Xcode version: 8.3.2

Arrangement: One primary target, with two embedded projects.

Test Methodology

The methodology I used was quite simple, and designed around “real life use” of my computers for Xcode development:

  1. Clean the project, manually delete the entire DerivedData folder.
  2. Shut down the computer
  3. Turn the computer back on
  4. Open the project
  5. Select the “generic ios device” target OS, and build the project (measurement #1)
  6. Clean the project, close Xcode, manually delete DerivedData (again)
  7. Launch Xcode, build the project again (measurement #2)

I planned the two trials to record the experience of building a project that isn’t currently in a disk cache, then building it again after macOS had the opportunity to keep files in disk cache. As the numbers below bear out, this made virtually no difference for the two SSD-based computers, but made a huge difference for the iMac with the Fusion disk.

For all trials, I made sure the computers were on AC power, no other applications were running — in fact I had done nothing since booting each machine except run XCode to time the tests.

I ran the test with three different computers, described below.

2015 15-inch (Retina) MacBook Pro Core i7

Test subject #1 is a 2015 MacBook Pro with a Core i7 CPU, SSD and 16GB RAM. This is a pretty standard “developer workstation” that many serious developers would select. Indeed my tests do support this is probably the best balance of power and portability for a developer (of the three test subjects).

2015 27-inch (5K) iMac Core i5

Test subject #2 is a 2015 iMac with a Core i5 CPU, Spinning Fusion drive and 32GB RAM. This is my “daily driver” development workstation. While a Core i5 machine with a spinning disk may not sound like a natural choice for a developer, the numbers below bear out that this is actually the most performant machine of the three by a decent margin — for this use case. Of course while it has the most RAM, largest screen and most storage, it has zero portability. Trade-offs…

2016 13-inch MacBook Pro (no touch bar) Core i7

I purchased this machine as a “travel laptop”. I love the portability of it, and it’s more than adequate for me as a mobile development workstation for short stints. It’s especially awesome for use on airplanes and giving presentations. However, I had wondered whether the 2-core i7 made any difference for Xcode builds vs. the 4-core i5 in my “daily driver” iMac, or the 4-core i7 in the 15″ MBP. Spoiler alert: it does. It really, really does.

Results

Here’s a summary of the system configurations, configuration costs and build timings using each machine with an identical set of code and the same build process.

One note: the fourth row is a computer I didn’t test because I don’t have one. I included it because that’s the system I would need buy if I wanted to trade in my current iMac+13″ MacBook pairing. I could make due with a base model upgraded to 1TB storage.

Note: the prices are what I paid for this equipment (or in the case of the 2015 15″ which I don’t own, its cost new from Apple as of this date).

My observations

  • Intuitively, I would have expected the 2015 MBP with the Core i7 to beat the 2015 iMac with the Core i5 — but the i5 iMac was the fastest. It’s only a difference of 12 seconds, but it’s still better performance for lower cost.
  • I didn’t necessarily expect the Fusion featured iMac spinning disk to catch up with the SSD machines (after it had a chance to cache the project) — but it did. In my use case of repetitive compiles in Xcode, I perceive no benefit to an SSD-based iMac vs the much less expensive Fusion drive.
  • It’s unfortunate that the 13″ MBP can only be ordered with 2 cores. Both the 4-Core iMac and 4-Core 15″ MBP blow right past the 2-core 13″ MacBook Pro.
  • The biggest determinant of performance seems to be how many CPU cores area available to the build process.
  • The i5/i7 architecture seems to make no difference — for this use case, at least.

What will I buy next time?

Since I primarily work in my office, and travel for business only occasionally, the iMac plus lower end MacBook for the road still works the best for me. A 5K iMac ($2,499) plus a basic 13″ MBP for travel ($1,699) costs less than a mid-range 2016 15″ MBP ($3,199) plus the 5K UltraFine display ($1,299). Your mileage may vary, but for my purposes the speed of the iMac and the lightest, most coach-class friendly travel machine is the best of both worlds. Plus my livelihood depends on a working computer every day, so having a backup to my primary machine gives me peace of mind.

Using the System Font Efficiently in iOS

Often an app designer specifies custom fonts out of a perceived need for uniqueness, but very often the built-in iOS system font is entirely appropriate. One advantage of the system-provided font is how simple it is to load them from code. Here’s how to do it:

Call systemFontOfSize

When using the system font, call the static routine systemFont to generate a font with a weight and height.

UIFont.systemFont(ofSize: <fontSize>, weight: <predefined weight value>)

Specify a font size for the height of the font

The fontSize is per usual — for example 10.0 for a standard reading font.

Specify a font weight using predefined constants

For predefined weight value, pass in one of the following constants, which will let iOS go find the correct font for you from the pre-installed System font used on the device.

UIFontWeightUltraLight UIFontWeightThin UIFontWeightLight UIFontWeightRegular UIFontWeightMedium UIFontWeightSemibold UIFontWeightBold UIFontWeightHeavy

For Example

Example valid calls:

let fontNormal = UIFont.systemFont(ofSize: 10.0, weight: UIFontWeightLight) let fontHeading = UIFont.systemFont(ofSize: 12.0, weight: UIFontWeightBold)

Caveats

There are a few caveats to be aware of:

  • The System font used on different versions of iOS is not necessarily the same. For example on iOS 9, the font is San Francisco. For iOS 8 the font is Helvetica Neue. This could be good or bad, depending on your point of view. It’s good that your app will automatically adopt whatever fresh font Apple introduces in the future (if it does). On the other hand, if you use System font, you don’t have control over the font rendered in your app.
  • The systemFont (which used to be called systemFontOfSize before Swift 3.0, is available only on iOS 8.2 or later. This shortcut method won’t work if you’re supporting a codebase with an OS target before the minimum. Be warned.

Originally published at rekerrsive.ghost.io on December 1, 2016.

Testing whether a view is currently visible

When manipulating iOS UI from background threads, or in response to NSNotification messages, you won’t always be sure that the view your controller is working with is on-screen. How can you check?

Relatively easy. Here’s a simple check from within the context of a View’s ViewController:

if self.isViewLoaded() && self.view.window != nil { // do something }

This is appropriate when the “something” shouldn’t be executed unless the view is currently visible to the user.

Facebook login using the iOS API with Swift

A common requirement for consumer mobile apps is to allow users to authenticate with their FaceBook credentials. Let’s explore why, and then go ahead and make the integration with iOS and Swift

A common requirement for consumer mobile apps is to allow users to authenticate with their FaceBook credentials. Let’s explore why, and then go ahead and make the integration with iOS and Swift

Why use Facebook authentication?

Why would we want to use Facebook auth instead of providing our own authentication database? Really it boils down to two reasons:

  1. Easier user experience. If we let users use their Facebook accounts to authenticate to our application, they don’t need to remember a new user id and password, and are more likely to go ahead and use our app because it’s a frictionless experience.
  2. Easier and more secure for our app. Since we’re effectively “outsourcing” identity to Facebook, we don’t need to manage/secure user passwords, implement password reset processes and so on.

Overall Process

Here’s the overall process of integrating Facebook Identity:

  1. Register our app on Facebook. This lets Facebook know who we are, when authentication requests come to their API. In the setup process we’ll also communicate which Facebook services we’re going to use. Some of the services we can integrate into our app require additional Facebook review of us. But the basic authentication in this post does not.
  2. Integrate the Facebook API into our XCode project. Just like any integration, we’ll need to add some frameworks. In this project I’ll be using CocoaPods to download and install the Facebook frameworks.
  3. Add a button to the app UI to initiate the Facebook request. This can be done in code or in storyboard design. I’ll use the storyboard method.
  4. Capture the Facebook user ID, and insert it into our own web service database so we can associate the Facebook users with one of our users.

Register with Facebook

Facebook provides a Quick Start for iOS tool to create app IDs, which I’ll be using.

  1. On the Quick Start form, provide a display name for the new App, adn then click on the Create New Facebook App ID button.
  1. The next step is to provide a contact e-mail and an application category. After providing this info, click the Create App ID button.
  1. From here, the Facebook Quick Start screens are providing us some great step-by-step instructions what to do next. Capture the information about the info.plist contents, which we’ll later add to our app.
  1. Mid-way down this form is a switch to indicate whether the app we’re creating contains in-app purchases. The default is Yes, so if your app doesn’t include them (or if you don’t want to use FB to track them), slide this button to the No position.

Finally — and this may be the most important step! — provide the Bundle Identifier for the app to Facebook. When our app makes calls to the FB API, it will send the Bundle ID, which FB will use to match our app to the App ID record we just created within FB.

Adding the Facebook API to our XCode Project

Next up, we need to add the Facebook API to our XCode project. This can be done by downloading the Facebook frameworks and manually integrating them, but I always find using CocoaPods more productive and a better way to keep 3rd-party modules up-to-date over time.

Install CocoaPods

If you’re not familiar with CocoaPods, it’s a Ruby-based package manager that modifies your XCode project to include 3rd-party modules (like the Facebook API). CocoaPods will configure an XCode workspace that includes your project, and additional projects for the 3rd-party components.

If you don’t have CocoaPods installed on your development workstation, or don’t know what it is, browse over to https://cocoapods.org to learn about it and install it before continuing.

Create the Podfile

After creating your base XCode project, open a bash shell in the same folder where your .xcodeproj is located, and then run the following command to create a new Podfile

$ pod init

Next edit the Podfile (I’m using nano, but you can use any text editor). Update the new Podfile to look as follows:

At this point, your project folder should look something like this:

After updating the Podfile, make sure XCode is closed, and then run a the following command to download the Facebook frameworks and configure your XCode workspace:

$ pod install

Once the frameworks are installed and the .xcworkspace is created, your folder should now look like this:

From this point, you should never have a reason to open your .xcodeproj project, and from now on always open the .xcworkspace file instead. The Facebook API frameworks will be new projects in the workspace, referenced by your original project while editing and building the project.

Back in step 1, Facebook gave us text to add to our .plist file, so open the .xcworkspace, and then open the .plist file as text (so we can paste in the entries FB gave us).

Add the entries from the Facebook Quick Start screen before the closing </dict> tag.

Setup the AppDelegate

Two methods to update int he AppDelegate class. The first is our old friend application : didFinishLaunchingWithOptions. In this method, just add a call to pass on the launch parameters to the Facebook API:

FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)

Next, add the delegate method application : open url, and fill it out with a similar call that passes on to Facebook API:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { let sourceApplication: String? = options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: sourceApplication, annotation: nil) }

With these changes, the AppDelegate will make calls to the Facebook API when initially launched (didFinishLaunchingWithOptions method), and when launched after the Facebook login is completed (open url method).

Configure the UI

Since this is a test application, I’ve created it as a simple single view app. In the default storyboard, I’ve added the following controls:

  • A UIView in the shape of a button, with the class name set to FBSDKLoginButton, connected to a class outlet named loginButton
  • A UIView in the shape of a square profile photo, with the class name set to FBSDKProfilePictureView. No class outlet is needed.
  • A UILabel, with a class outlet named userIdLabel
  • A UILabel, with a class outlet named userNameLabel

In the storyboard, the form looks like so:

Add code to the ViewController

There’s not much code involved in making this login button work. Its presence on the form is enough to enable it. The code we add really is just to set a couple properties, and add delegate methods that are called as the user interacts with the Facebook login process.

Add the Import

import FBSDKLoginKit

Declare our class with the delegate protocol

class ViewController: UIViewController, FBSDKLoginButtonDelegate {

Connect Outlets

@IBOutlet weak var loginButton: FBSDKLoginButton! @IBOutlet weak var userIdLabel: UILabel! @IBOutlet weak var userNameLabel: UILabel!

Configure the button

In the ViewDidLoad method, add the following configuration lines:

loginButton.delegate = self loginButton.readPermissions = ["public_profile", "email", "user_friends"] FBSDKProfile.enableUpdates(onAccessTokenChange: true)
  • The first line sets this ViewController as the delegate for the Facebook login events
  • The second line lets the FB login process know what read permissions we’re asking the user to approve
  • The third line asks the SDK to send a notification if/when the user’s profile changes.

Create a profile change listener

Just below the button configuration lines, add the following code to receive a notification when the user’s profile is updated (asynchronously) after the login completes.

NotificationCenter.default.addObserver( forName: NSNotification.Name.FBSDKProfileDidChange, object: nil, queue: nil) { (Notification) in if let profile = FBSDKProfile.current(), let firstName = profile.firstName, let lastName = profile.lastName { self.userNameLabel.text = "(firstName) (lastName)" } else { self.userNameLabel.text = "Unknown" } }

The listener is needed because the profile won’t be completely populated at the moment the login completes. So effectively this code will wait around for the API to complete the profile, then will be called.

After the user interacts with Facebook to login, we’ll be notified when the login is completed, and if the user presses the button again to logout.

func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if let result = result { self.userIdLabel.text = result.token.userID // Notify our web API that this user has logged in with Facebook } } func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) { print("Logging out") }

With these methods implemented, the application is complete.

If using Simulator, Turn Keychain Sharing on

If you don’t need to test using a simulator, and will use a physical device for testing, proceed to the next section — you’re good to go.

However, if you want to run this application on a simulator and connect to Facebook, there’s one more small thing to do — enable Keychain Sharing for your target.

Select your target, and in the Capabilities tab, slide the Keychain Sharing switch to the “On” position. Similar to the below (image credit:

Running the application

When we run this application, the first thing we see is the main form, with the login button waiting to be pressed:

After pressing the login button, the application will be put in background while Safari launches to ask the user to login within the Facebook mobile experience. In this screen I’m informed that I’ve already authorized this app once, so I only have to confirm that I still want to login.

After I finish with Facebook, I’m transferred again back to AppDelegate, within that open url method we implemented earlier. Afterward, the form is shown again, this time with my profile photo, name and Facebook ID.

And that’s it!

Swift 3.0 substrings made easy

Swift is a fantastic, modern language, and has fast become my favorite. So much of what’s built into it is intuitive, simple and makes coding much more expressive than older, more syntactically heavy programming languages.

Swift is a fantastic, modern language, and has fast become my favorite. So much of what’s built into it is intuitive, simple and makes coding much more expressive than older, more syntactically heavy programming languages.

But…sometimes its sophistication makes what was simple in older languages more complicated. Case in point is taking substrings. Substrings are not difficult to deal with in Swift, but personally I find the syntax confusing. Many others do as well, and it’s common to address the confusion with an extension pattern.

Let’s first look at some basics of how to take substrings “out of the box”, and then look at a pretty common extension approach to make the substring syntax more approachable and simple.

The Range Construct

The foundation of taking substrings in Swift is using Range objects. Range is just what it sounds like — an encapsulation of a beginning and ending index within a String.

Take a look at he following quick example. In the example, the .range function is used to get the start and end index of the word “quick” within the larger string. Then, if the range is not nil, that word is extracted using the range bounds, and printed to the console.

This is something we might do in real life, and the Swift syntax is expressive and simple to remember.

// find and return a substring using Swift 3.0 let sentence = "The quick brown fox jumped over the lazy dog." if let quick = sentence.range(of: "quick") { let word = sentence[quick.lowerBound..<quick.upperBound] print(word) // prints "quick" }

The Range syntax is used to extract strings by known index as well, but in this case the syntax really gets in the way and is not simple or easy to read.

Before getting into it, let’s review how this would be done in C++:

// find and return a substring at known location using C++ string sentence = "The quick brown fox jumped over the lazy dog."; string word = sentence.Substring(4, 5); cout << word; // prints "quick"

The C++ is syntactically simple and easy to understand. Substring just starts at the fifth character, and extracts five characters. Simple.

Swift is similar to the C++ standard library conceptually, but the use of the Range construction. This results in a significantly more verbose statement to accomplish what is simple to do in C++:

let sentence = "The quick brown fox jumped over the lazy dog." let substringNoExtension = sentence[sentence.index(sentence.startIndex, offsetBy: 4)...sentence.index(sentence.startIndex, offsetBy: 8)] print(substringNoExtension) // prints "quick"

The syntax is actually quite similar to the C++ version, but let’s face it — it’s long and tedious. The interpretation is “extract from the string from index 4 to index 8 inclusive”. OK, simple concept, but wow! Look at all that syntax. If you need to do this once, not a problem, but what if the code uses offsets frequently?

Swift using an Extension

Luckily, Swift has the concept of extensions which allow us to essentially append new methods and data to existing classes and structs — even ones where we don’t have the source code or aren’t allowed to inherit new objects from them.

So first, let’s add an extension that adds a subscript operator that accepts a closed range:

extension String { subscript(range: ClosedRange<Int>) -> String { let lowerIndex = index(startIndex, offsetBy: max(0,range.lowerBound), limitedBy: endIndex) ?? endIndex return substring( with: lowerIndex..<(index(lowerIndex, offsetBy: range.upperBound - range.lowerBound + 1, limitedBy: endIndex) ?? endIndex)) } }

OK, so yes, I know…this is a lot of code too. But remember, this is an extension, and you just need to add this extension method to global scope one time, then use it over and over wherever you need it.

Now with the extension added to global scope, the substring with known indexes becomes the following:

let sentence = "The quick brown fox jumped over the lazy dog." let substringWithExtension = sentence[4...8] print(substringWithExtension) // prints "quick"

This syntax is even simpler than the original C++, and it’s immediately intuitive that we’re taking a range of characters from the 4th to the 8th character.

Simple!

Full Extension Example

Below is a more complete extension to add a somewhat more complete substring extension to String which builds on the simple single example above.

extension String { subscript(i: Int) -> String { guard i >= 0 && i < characters.count else { return "" } return String(self[index(startIndex, offsetBy: i)]) } subscript(range: Range<Int>) -> String { let lowerIndex = index(startIndex, offsetBy: max(0,range.lowerBound), limitedBy: endIndex) ?? endIndex return substring(with: lowerIndex..<(index(lowerIndex, offsetBy: range.upperBound - range.lowerBound, limitedBy: endIndex) ?? endIndex)) } subscript(range: ClosedRange<Int>) -> String { let lowerIndex = index(startIndex, offsetBy: max(0,range.lowerBound), limitedBy: endIndex) ?? endIndex return substring(with: lowerIndex..<(index(lowerIndex, offsetBy: range.upperBound - range.lowerBound + 1, limitedBy: endIndex) ?? endIndex)) } }

Big Improvements in iOS10 Swift3 CoreData

Having a built-in relational database in iOS via CoreData is a pretty nice feature of the mobile OS. I’ve always liked using it, but like many developers I’ve never appreciated the volume of boilerplate code to create and maintain just to setup the basic scaffolding in a new project.

Having a built-in relational database in iOS via CoreData is a pretty nice feature of the mobile OS. I’ve always liked using it, but like many developers I’ve never appreciated the volume of boilerplate code to create and maintain just to setup the basic scaffolding in a new project.

As much as I appreciate CoreData being totally a “built in” database, the fit and finish of the API and integration just lacked polish and ease of use for Swift development.

Well with iOS 10 — I have to say “not anymore”. Earlier this week I setup the my first project targeting iOS 10 with CoreData, and it was just a dream to work with. With a little data model definition and a few lines of initialization in AppDelegate, I had a full database defined and running. Love it.

This isn’t a tutorial on how to setup a new project with CoreData in iOS 10, but I’ll note a few of the changes that make the process more streamlined.

Source of Example

The project discussion below is from a an iOS 10 upgrade of one of my demo apps in the app store. The code isn’t exactly from the code base, but is excerpted from it.

Data Model Definition — mostly the same

Defining the data model in XCode is very much like before. If you use CoreData, all skills transfer. Create entities and attributes, etc.

The significant difference is to pay attention to the Codegen drop-down, which flags to XCode whether to create a class, a class extension, or to do nothing with your entities. In the screen grab below, I’ve selected Class Definition, telling XCode I want it to generate a full Class named Terminal which will be available to the project.

When the project builds, XCode generates a class (and extension) behind the scenes to provide the normal set of Manged Object functionality CoreData expects. Did you notice — no need to generate the model manually, and remember to regenerate it manually with each attribute change! Stellar!

AppDelegate Scaffolding

Also streamlined is the amount of scaffolding work in AppDelegate. This is reduced from dozens of lines of boilerplate code to create/maintain, down to just a very few.

Sometimes you need to hand tune that scaffolding code for performance etc. This is still possible, since CoreData is back there and properties and methods are accessible. But now is more by exception rather than a requirement even for simple programs. Easy on-ramp, then add complexity as needed.

In this snippet I’ve eliminated code not relevant to CoreData, and as you can see, the setup required is minimal:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { coreDataStack = NSPersistentContainer(name: "Terminals") coreDataStack.loadPersistentStores { (description, error) in if let error = error { // Handle error appropriately } } return true }

That’s pretty much done. All that extra code in AppDelegate from previous versions is just gone! Again, there’s tweaking and tuning depending on the requirements of the app, but a minimal CoreData app now requires so much less code to get up and running!

Accessing data in the database

Now that the database is up and running, how to insert a record? Let’s look at the code. Again, the code is kept minimal for clarity.

func insertRow(context : NSManagedObjectContext, name : String, city : String, lat : Double, lon : Double) { do { let terminal = Terminal(context: context) terminal.name = name terminal.city = city terminal.lat = lat terminal.lon = lon try context.save() } catch { // Handle error appropriately } }

Wow, pretty straightforward!

While this isn’t a complete example of writing an iOS 10 CoreData app from end-to-end, I hope it illustrates just how much more straightforward this is for the developer.

Accessing AppDelegate in swift 1…3

We all learned in college that global variables are undesirable, but most iOS applications need to access some global members of the shared UIApplication object.

We all learned in college that global variables are undesirable, but most iOS applications need to access some global members of the shared UIApplication object.

I appreciate that the Swift syntax is getting better and better, but it’s still a moving target and challenges my noodle to keep up.

Here’s a quick cheat sheet on accessing AppDelegate through the versions. In each example, we’re getting our shared appDelegate to check a variable called isProduction

Swift 3

let appDelegate = UIApplication.shared.delegate as! AppDelegate let isProd = appDelegate.isProduction

Swift 1.2–2.0

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate let isProd = appDelegate.isProduction

Swift 0..<1.2

let appDelegate = UIApplication.sharedApplication as AppDelegate let isProd = appDelegate.isProduction

Swift 3.0 for loop syntax

Since most of my coding is in Swift for the last few years, I’ve been adjusting to its more expressive syntax of the for loop. Now that the old “classic” for with semicolon syntax will start to be unsupported in Swift, I’m putting the real pedal to the metal on learning all the new options!

Since most of my coding is in Swift for the last few years, I’ve been adjusting to its more expressive syntax of the for loop. Now that the old “classic” for with semicolon syntax will start to be unsupported in Swift, I’m putting the real pedal to the metal on learning all the new options!

If you’ve been programming for a little while, whether you started with K&R C (like me!), or even C++ or Java, you’re probably used to the following C-based for loop syntax:

for (int i=0; i<10; i++) { printf("%d", i); } // printf() is called 10 times

So for my reference (and yours, if you like) here are the things I need to bang to rote memory:

Old timey for loop (K&R C — ish)

for i in stride(from: 0, to: 10, by: 1) { print("(i)") } // print() is called 10 times

Ok, this is using the stride function, which I don’t see a lot when googling around for for loop syntax. But I actually kind of like it. Yes, it’s a little on the verbose side. But it really tells you exactly what’s going on, doesn’t it?

In classic C syntax, the most commonly used increment expression is i++, which means “increment by 1”. But sometimes you want to advance by other than 1 discrete digit, such as:

for (int i=0; i<10; i += 2) { printf("%d", i); } // printf() called 5 times

In swift, this is accomplished by swapping to: with through:

for i in stride(from: 1, through: 10, by: 2) { print(i) } // print() is called 5 times

For-In syntax

Ok, so I do like the stride. But like most, I use the more concise For-In syntax more often. And unlike the old “comfortable pair of jeans” K&R C semicolon syntax, it’s shorter and makes more sense expressively:

for i in 0..<10 { print("(i)") } // print() is called 10 times

You have to admit that’s a lot less typing than K&R C, huh?

This syntax also can handle an inclusive loop (also running on the end number), by just swapping the < for a .:

for i in 0...10 { print("(i)") } // print() is called 11 times

Personally, I find ... a little weird, but I’m getting used to it. In English grammer it should be .., which is an inclusive list, but if that were true for this syntax there would be loads of mistakes caused when ..< was intended, but someone forgot to type the < at the end. So this seems a practical necessity.

Iterating over an array

I find the most common thing I do with this kind of for loop iteration is iterating over arrays. This has been true ever since the old C days, and it’s just as true with Swift. Mercifully, the Swift language provides a syntax just for this senario:

let intArray = [1, 3, 5, 6, 7, 333, 33_223] for i in intArray { print("(i)") } // print() is called 7 times

This works for any kind of array, and is just a lovely way to walk an array.

Checking out AWS CodeCommit

Recently the git cloud server landscape became very interesting with the announcement by GitHub that the new pricing would be much more friendly toward users with many private repositories.

Recently the git cloud server landscape became very interesting with the announcement by GitHub that the new pricing would be much more friendly toward users with many private repositories.

Probably one reason for this is that the alternatives out there for low cost git hosting keep expanding, and GitHub must have seen the writing on the wall that it needed to get less stingy about private repositories.

But while GitHub is the most well known cloud repo offering, it’s not the only game in town. BitBucket, GitLab, and Microsoft Visual Studio Online are among other highly respectable code repository hosting platforms I’ve used that offer compelling services at similar prices.

Last year Amazon introduced its own Git-based repo offering, called CodeCommit. I’ve been intending to try it out, and finally have gotten around to it. Based on my initial experience, I’m glad I did!

AWS CodeCommit

I suspect one of the reasons pushing GitHub in th direction of free private repos is the introduction of CodeCommit by AWS last year. CodeCommit offers a very economical solution for private repos based on its uber-dependable AWS public cloud hosting platform.

While AWS isn’t providing all that GitHub has on offer — yet — it’s still a viable alternative for the basics of git hosting, and like everything else in AWS will probably evolve to compete beyond core functions over time.

The rest of this post is just a quick test I decided to do to create an XCode git repo on AWS CodeCommit in a similar way that I would usually do with GitHub. Then a quick summary with some thoughts at the end.

Uploading SSH Keys & Setting up IAM

As with GitHub and other git hosting services, the first step is to have a user account, and upload your public SSH key to that account.

Since CodeCommit is on AWS, the user account you need is an IAM Account. I already had one in my AWS account, so all I needed to do was to create a new SSH key pair on my Mac, add the public key to my IAM account on AWS, and add my IAM user to the policies as outlined in the getting started guide.

I found this process more complex than the same configuration on GitHub or BitBucket. For those not already familiar with AWS policies and the general flow of AWS portal administration, this could be off-putting. While I don’t ever remember reading the detailed instructions on GitHub (and I survived just fine), you definitely can’t skip reading the AWS CodeCommit documentation (though it is brief and well illustrated, so not a big chore). On the other hand, AWS is offering quite a bit more granular control and security with its platform — this is a trade-off. For my part I’ll gladly take extra security control in exchange for the effort of learning how to configure it.

Updating the SSH config file

The local side of the SSH authentication is to update the file ~/.ssh/config to let git know which private key to use when connecting to the CodeCommit server. These entries are similar to what you would have done using GitHub or BitBucket. Same process — this is a git thing, not an AWS thing.

Follow the instructions in points 10 and 11 in the the getting started guide, which explains how to do this quite clearly: CodeCommit Getting Started Guide. Thanks again AWS for great documentation!

Creating a shell repo

I tend to create a repo on a cloud provider’s system, and then connect my local git repo to it as a remote. CodeCommit supports this just like other providers. It also supports creating a remote and pulling the local from there — just like the providers.

Overall if you’ve used GitHub, this part of the process will feel very familiar.

Creating the repo can be done from the web console, which I found very simple. Alternatively, it can be done from the AWS CLI, which I found quite convenient, and easier to illustrate in a blog post, so I’ll use CLI from here.

My next step was to enter the command to create a repo, executed from any folder on my Mac:

$ aws codecommit create-repository --repository-name Test1 --repository-description "Quick test repo"

CodeCommit responded as such.

"Quick test repo" { "repositoryMetadata": { "repositoryName": "Test1", "cloneUrlSsh": "ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/Test1", "lastModifiedDate": 1463989097.607, "repositoryDescription": "Quick test repo", "cloneUrlHttp": "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/Test1", "creationDate": 1463989097.607, "repositoryId": "e889d5cf-7c80-498e-ba56-884b468eba97", "Arn": "arn:aws:codecommit:us-east-1:************:Test1", "accountId": "*************" } }

So far, so good. Note the cloneUrlSsh, which is used n subsequent steps.

Connecting the XCode Project

I created my original project with XCode, and ticked the box to create a local git repository — so my local git work is 99% done, and all I need to do is add CodeConnect as a remote repo to the local one XCode created for me. Again, I’ll do that at the command line, but this time executed from the XCode project folder:

$ git remote add origin ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/Test1

There’s no response to this command, but for the curious, the effect of it can be checked in the .git/config file underneath the project folder:

[core] bare = false filemode = true ignorecase = true precomposeunicode = true logallrefupdates = true [core] repositoryformatversion = 0 [remote "origin"] url = ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/Test1 fetch = +refs/heads/*:refs/remotes/origin/*

Pushing the content

With all the setup complete, the proof is in the ability to push the repo content into AWS. Just for good measure, I’ll add files, execute a first commit, and then a push.

$ git add . $ git commit -m "First commit" $ git push origin master

Adding the ssh key passphrase to keychain

I did encounter one glitch — when trying to use git to push to the repo to the remote, I encountered a public key error, and my ssh key passphrase was failing to add to keychain via the interactive popup dialog box. To overcome this, I manually added the passphrase to keychain.

/usr/bin/ssh-add -k ~/.ssh/rob_kerr_aws_ssh

After the manual key add, the push worked just fine, and lightning fast:

Counting objects: 25, done. Delta compression using up to 4 threads. Compressing objects: 100% (21/21), done. Writing objects: 100% (25/25), 11.74 KiB | 0 bytes/s, done. Total 25 (delta 1), reused 0 (delta 0) remote: To ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/Test1 * [new branch] master -> master

Confirming the files made it to the remote repo

At this point all seemed to be OK, and the experience very much like using GitHub, BitBucket, or even a repo on OSX Server.

Just to check, I took a peek at the repo from the AWS portal — and found my files in the remote repo as expeted:

Generally I like AWS CodeCommit. Granted this entire try-out took just a few minutes, and I haven’t evaluated the full breadth of features nor used CodeCommit in a real project workflow as yet. But, for what it does, it looks pretty great, and the [CodeCommit pricing](CodeCommit pricing) for my use case would effectively be free — even less than the $7/month GitHub now charges for unlimited private repos on individual accounts.

Will I be switching to CodeCommit? Possibly. While GitHub provides more features and a more mature portal experience, at first glance CodeCommit seems to have the basic block and tackle hosted git covered, and the free tier limits seem to give me plenty of headroom. I’m happy to save some coin without losing many features I use. And since I use AWS already, I wouldn’t mind having one less cloud services account to keep track of.

Designing for scale in a Cloud/Mobile/IoT world

Message queueing to provide application scalability has been a common pattern for decades. In the last few years a new term has been coined — Internet of Things (IoT) that puts a brand name over highly scalable message-based computing.

Message queueing to provide application scalability has been a common pattern for decades. In the last few years a new term has been coined — Internet of Things (IoT) that puts a brand name over highly scalable message-based computing.

Why is IoT a thing?

The emergence of the IoT “brand” demonstrates that a pattern needed in perhaps 1% of use cases in the past is becoming mainstream. In a world where smartphones are used by the majority of consumers, computing systems that support transactions from thousands of remote devices are more common.

20 years ago, a message queueing pattern would be implemented in a traditional, on-premises technology. For example I used Microsoft Message Queuing (MSMQ) “back in the day”, i.e. with Windows NT 4.0. Today, it makes a lot of sense to use a public cloud provider like Microsoft Azure or Amazon AWS to implement application message queues, since these services are more cost effective and scalable than on-premises alternatives.

Why use a Queuing pattern?

Almost any system that has more clients than servers can generate spikes in volume that exceed the ability of back-end resources. Anyone who has been stuck in a customer service hold queue has experienced a supply/demand imbalance which has been mitigated through the use of queuing. For most customers, hold music is preferable to a busy signal, and technology makes that happen.

For an IoT or mobile device architecture, it’s basically the same problem with the same solution. Following the call center analogy, the “callers” in the IoT scenario may be mobile devices, industrial sensors or thermostats. The “call center agents” are event processors that pick up application messages, read the data contained in them, update databases, send notifications, and/or conduct streaming analysis.

Queue/Event Architecture Diagram

The following diagram illustrates a general model of an IoT processing architecture that utilizes a public cloud provider’s infrastructure.

I’ve differentiated between “Message” queues and “Event” queues, as these highlight overlapping but different use cases. Both AWS and Azure provide differentiated services as well, which I’ll discuss below.

In the diagram above, transactions are sent by a potentially large number of client devices. Without a message queue architecture, the solution architect needs to scale back-end web front ends and databases to meet peak demand at all times. That can get (really) expensive!

Message Queue Processing

Historically, the message queue architecture has been used to model transaction flows that needed to be highly consistent and reliable, but don’t necessarily need a realtime response of 10–20 milliseconds. Typically we’d want to be sure that every message arrived without fail, the sequence of processing was perfectly FIFO, that confirmations or responses were dispatched on return queues, etc. This is a “message queue” use case, and is important for many use cases.

Event Processing

What if the use case is more “event” oriented? If the application sends a stream of navigation clicks within an application, what’s the response? There isn’t one, is there? This might also be true if the application is to stream temperature or rainfall measurements. These are all events that require no response at all — maybe a simpler architecture would be more appropriate?

Indeed, as IoT has surfaced, a lot more emphasis has been placed on processing events, and products specifically targeted for event processing have become common place.

But is there an advantage to a technology specifically geared to event processing? The answer is yes — an event processing system is less expensive to provision and operate. Maybe 90% less expensive!

Public Cloud Offerings

Public cloud infrastructures invariably support message and event processing services. The two most popular services — AWS and Azure — have specific offerings for both Message Queue and Event processing.

AzureAWS Application Message QueuingAzure Service BusAmazon SQS Event QueuingAzure Event HubAmazon Kinesis

Each cloud provider has somewhat different approaches, but in general message vs. event use cases differentiate the most appropriate service selection. Selecting the right service is important to meet application needs appropriately, as well as keeping operating costs minimized.

Further Reading

Want to learn more about cloud message queues and event processing? Check out these other excellent articles:

Event Hubs vs. Azure Messaging

Amazon SQS — Message Queing Service

Amazon Kinesis

Azure Service Bus Fundamentals

Azure Event Hubs Overview

Publishing Data from iOS Devices to Azure Event Hubs

Connecting Native iOS apps to to SQL Server Analysis Services Cubes

Using a web service pattern, we can connect a native mobile application with just about any data source. SSAS is most often used as a backend database for Microsoft Excel and out-of-the-box BI Platforms to implement slice-and-dice ad-hoc query use cases. But could we connect a native mobile application to SSAS to provide a high-performance analytical database? Absolutely! Let’s look at how we can architect a solid solution connecting a Swift-based iOS native application with an on-premises deployed Analysis Services cube.

Using a web service pattern, we can connect a native mobile application with just about any data source. SSAS is most often used as a backend database for Microsoft Excel and out-of-the-box BI Platforms to implement slice-and-dice ad-hoc query use cases. But could we connect a native mobile application to SSAS to provide a high-performance analytical database? Absolutely! Let’s look at how we can architect a solid solution connecting a Swift-based iOS native application with an on-premises deployed Analysis Services cube.

Architecture

Since there’s no direct client framework for iOS (or Android) to connect to SSAS, we’ll use the familiar pattern of placing a JSON web service in front of the SSAS database. Client drivers for SSAS provided by Microsoft are supported on Windows, so the web service I’ll create will use .NET, and the C# code will leverage the standard ADOMD client drivers provided by Microsoft in the SQL Server Feature Pack Download.

I’ll develop my client application using Swift and XCode, targeting iOS natively. The client could of course be developed in many different ways — Native iOS, Native Android, Xamarin, Ionic, etc.

The final architecture looks as follows:

iOS Application design

Before going further, let’s look at the design of the iOS application that will be the result of the development steps. Here’s the UI we’ll be creating — a pretty basic KPI Scorecard displayed on an iPhone, with data served up by our .NET web service.

The key of the data integration within the iOS app is swift code in the ViewController that contains the KPI list in the screen shot. Here’s an abbreviated version (error handling and some complexity removed). Note that there’s nothing really different about this compared with any other data source — all the complexity is encapsulated in the web service.

// excerpt from DashDetailViewController.swift 
func getWebServiceData() { 
// Setup headers var headers : [String : String] = [ "Content-Type": "application/json" ] // Add authorization let loginData: NSData = auth.dataUsingEncoding(NSUTF8StringEncoding)! let base64AuthString = loginData.base64EncodedStringWithOptions([]) headers["Authorization"] = "Basic " + base64AuthString // Request to .NET + SSAS web service endpoint if let url = dashParameters?.urlEndpoint, parms = dashParameters?.parameters { Alamofire.request(.POST, url, headers: headers, parameters: parms, encoding: .JSON) .responseJSON { response in let resultNSString = NSString(data: response.data!, encoding: NSUTF8StringEncoding)! // Tear down the package and iterate over the objects found inside if let package = response.result.value as? [String:AnyObject] { if let arr = package["data"] as? [AnyObject] { for (_, item) in arr.enumerate() { if let viz = item as? [String:AnyObject] { if let vizType = viz["vizType"] as? String { if vizType == "LineChart" { print("Calling addVizTrendLineChart") self.addVizTrendLineChart(viz) } if vizType == "KPIItem" { self.addVizKpi(viz) } } } } } self.collectionView?.reloadData() } } }

Write the MDX (or DAX) query

To create the data displayed in the iOS application, we need to query the Analysis Services cube. Like any database — SQL Server, Oracle, MongoDB, DocumentDB, etc., SSAS Cubes have a query language. And actually, they have two languages, depending on whether Analysis Services uses Multidimensional or Tabular modes. In this example, I’ve used MDX — but this technique works just as well with DAX.

Here’s the MDX to create the data set displayed above:

// TerritoryKpiList.mdx WITH MEMBER [Measures].[TerritoryLabel] AS [Sales Territory].[Sales Territory].CurrentMember.UniqueName MEMBER [Measures].[TerritoryKey] AS [Sales Territory].[Sales Territory].CurrentMember.Name MEMBER [Measures].[ChildCount] AS [Sales Territory].[Sales Territory].CurrentMember.Children.Count SELECT { [Measures].[TerritoryLabel], [Measures].[TerritoryKey], [Measures].[ChildCount], KPIValue("Revenue"), KPIGoal("Revenue"), KPIStatus("Revenue"), KPITrend("Revenue") } ON COLUMNS, NON EMPTY { (STRTOMEMBER(@TerritoryKey).Children) } ON ROWS FROM [Adventure Works] WHERE (STRTOMEMBER("[Date].[Fiscal].[Fiscal Year].&[" + @Year + "]"))

Note there are two bound parameters in the MDX query: TerritoryKey and Year. The iOS application passes these parameters in via a JSON object called dashParameters in the Swift code above. The web service retrieves them from the JSON parameter object, and injects them into the query via AdomdCommand.

Implementing the .NET Web Service

The core of delivering the SSAS data to the mobile application is a .NET web service, in this case developed with Visual Studio 2015 and C#. Implementing a .NET web service is straightforward and I won’t cover it step-by-step. But let’s look at some important concepts that enable connectivity to SSAS.

Just as with any database access from a web service, a database driver is needed. SSAS supports a few different options: OLEDB, XML/A, and ADOMD. I recommend ADOMD in almost every programmatic use case, and for this web service this is what I’ve used.

The first step to adding the ADOMD reference is to obtain and install the driver software from Microsoft. The best way to get this is to download it from the Microsoft SQL Feature Pack for the version of SQL Server you’ll be using. As of this writing, the latest production version is SQL Server 2014, and the feature pack is located here. SQL Server Feature Pack Download.

You’ll need to install ADOMD on your production web front-end, as well as on your .NET development workstation or VM.

After installing ADOMD on the web-front end on your development workstation, add a reference to it, so you your references look similar to this:

Implementing the ApiController

The key step is implementing the .NET controller. Again, this is straightforward and not really different than what you’d do with any kind of database backend — I won’t go through this step-by-step. But let’s look at the pieces of my controller that are relevant to retrieving and returning data from SSAS.

// excerpt from CorporateSalesController.cs 
namespace AdventureWorksAPI.Controllers { 
    public class CorporateSalesController : ApiController {    [HttpPost] public IHttpActionResult TerritoryKpiList([FromBody]WebServiceParameters jsonData) { string queryName = @"CorporateSalesTerritoryKpiList"; try { AdomdCommand cmd = ControllerHelper.setupMDXQuery(queryName); cmd.Parameters.Add("TerritoryKey", jsonData.territoryKey); cmd.Parameters.Add("Year", jsonData.year.ToString()); using (var reader = cmd.ExecuteReader()) { List<KpiItem> items = new List<KpiItem>(); while (reader.Read()) { Util.MdxUtils.debugDumpRow(reader); KpiItem item = new KpiItem(); int n = reader.FieldCount - 1; item.key = MdxUtils.readString(reader[n - 6]); item.name = MdxUtils.readString(reader[n - 5]); item.childCount = MdxUtils.readInt(reader[n - 4]); item.value = MdxUtils.readDouble(reader[n - 3]); item.goal = MdxUtils.readDouble(reader[n - 2]); item.status = MdxUtils.readInt(reader[n - 1]); item.trend = MdxUtils.readInt(reader[n - 0]); items.Add(item); } List<VizBase> data = new List<VizBase>(); data.Add(new KpiItemPackage( "TerritoryPerformance", "Territory Performance", items, "$#,###,###", "($#,###,###)", "api/CorporateSales/TerritoryDetailViews")); return Ok(new VisualizationPackageObject(data)); } } catch (Exception ex) { log.Error("*** ERROR: " + this.GetType().Name + "." + System.Reflection.MethodBase.GetCurrentMethod().Name + ": " + ex.Message); return InternalServerError(ex); } }

The controller is derived from the standard .NET ApiController base class, and uses an AdomdCommand to execute an MDX query against the SSAS cube. As a note — ADOMD can process MDX or DAX, so you can use either query language variant within this type of web service.

Note in the controller method above, you don’t actually see the MDX query as text. Since I don’t want to mix the MDX query with my C# source code, instead I put it on the file system of the web server, and use the method setupMDXQuery(queryName) to load it from disk and return it as an AdomdCommand. I find this much cleaner, and it allows the query strings to be maintained atomically and updated without changing the web service source code.

The code for this method is as follows:

// excerpt from ControllerHelper.cs public class ControllerHelper { public static AdomdCommand setupMDXQuery(string queryName) { string connString = Util.MdxUtils.getConnectionString(); string query = Util.MdxUtils.fetchNamedMDXQuery(queryName); // Trap for named query missing from file system if (query == null) { throw new Exception("Could not find named query " + queryName); } AdomdConnection conn = new AdomdConnection(); conn.ConnectionString = connString; conn.Open(); AdomdCommand cmd = new AdomdCommand(query); cmd.Connection = conn; return cmd; } }

The fetchNamedMDXQuery(queryName) is just a helper routine to provide I/O to the file system on the web server. That code is as follows:

// excerpt from MdxUtils.cs public static string fetchNamedMDXQuery(string queryName) { string cwd = HttpContext.Current.Server.MapPath("~"); string filePath = cwd + @"MDX" + queryName + ".mdx"; return File.ReadAllText(filePath); }

Connecting a Native Swift iOS App to Salesforce.com Data

Enterprise mobile apps most often need to integrate with broader platforms. This quickstart demonstrates how easy it is to integrate an iOS mobile app with the Salesforce.com platform.

Enterprise mobile apps most often need to integrate with broader platforms. This quickstart demonstrates how easy it is to integrate an iOS mobile app with the Salesforce.com platform.

Install Node.js and npm

If you haven’t installed node on your system, you’ll need to do this first. There are several methods for installing node. You can download node directly from the node.js web site, or use the Homebrew package manager to complete the installation for you.

After installing Node and npm, check that the software is installed before proceeding. An easy way to check that you’ll be able to use these tools is to check versions at the command line.

node --version npm -- version

Install forceios

The Salesforce SDK can automatically configure a new XCode project with development frameworks and correct settings. The SDK uses the Node npm command to create a new project. Npm is used to install the forceios package. Use the following command to install forceios on your development workstation globally:

sudo npm install forceios -g

Use Forceios to create your application

From the OSX command line.

forceios create

Respond to the various forceios commands to configure the XCode project correctly. Most of the responses to the project configuration will be obvious to iOS developers. The one that’s specific to the salesforce org is the “Connected App Callback URI”. This is a string you set within the Salesforce administration site when creating the Connected App this native iOS application will connect to.

The following is an example interactive session output from the foriceios configuration application.

Rob@robimac:~/Projects/blog/SalesForceSDKiOSExample$ forceios create Enter your application type (native, native_swift, react_native, hybrid_remote, or hybrid_local): native_swift Enter your application name: MTRolodex Enter the output directory for your app (defaults to the current directory): Enter the package name for your app (com.mycompany.my_app): com.mobiletoolworks.mtrolodex Enter your organization name (Acme, Inc.): Mobile Toolworks, LLC Enter your Connected App ID (defaults to the sample app's ID): Enter your Connected App Callback URI (defaults to the sample app's URI): sfdc://oauth-callback/salesforce Creating app in /Users/Rob/Projects/blog/SalesForceSDKiOSExample/MTRolodex Getting cocoapods dependencies Updating local specs repositories CocoaPods 1.0.0.beta.8 is available. To update use: `gem install cocoapods --pre` [!] This is a test version we'd love you to try. For more information see http://blog.cocoapods.org and the CHANGELOG for this version http://git.io/BaH8pQ. Analyzing dependencies Downloading dependencies Installing CocoaLumberjack (2.2.0) Installing SQLCipher (3.3.1) Installing SalesforceNetwork (4.1.1) Installing SalesforceRestAPI (4.1.1) Installing SalesforceSDKCore (4.1.1) Installing SmartStore (4.1.1) Installing SmartSync (4.1.1) Generating Pods project Integrating client project [!] Please close any current Xcode sessions and use `MTRolodex.xcworkspace` for this project from now on. Sending stats Sending stats Pod installation complete! There are 5 dependencies from the Podfile and 7 total pods installed. Successfully created native_swift app 'MTRolodex'.

After launching the XCode workspace — in this example “MTRolodex.workspace”, open the AppDelegate.swift file, and update the RemoteAccessConsumerKey and OAuthRedirectURI to match the values in your Salesforce.com connected app.

import Foundation import UIKit import SalesforceSDKCore let RemoteAccessConsumerKey = "3MVG98SW_UPr.GCjfe8JFg6qFEHxBqp3EzFBBoCZsnc2zuq5rgVVPJUbBh3T6zLyp1k13Tj_csFpIobDVSQDf"; let OAuthRedirectURI = "sfdc://oauth-callback/salesforce"; class AppDelegate : UIResponder, UIApplicationDelegate . .

These values identify the iOS native application and enable users to use the native app to access Salesforce resources.

The default boilerplate app generated by forceios lists the users of the Salesforce org. Let’s make a slight change to instead list the Accounts store in the org. To do this, change the loadView() method within the RootViewController.swift class file as follows:

override func loadView() { super.loadView() self.title = "Mobile SDK Sample App" let soql = "SELECT Id, Name, BillingCity FROM Account" let request = SFRestAPI.sharedInstance().requestForQuery(soql); SFRestAPI.sharedInstance().send(request, delegate: self); }

Build and run

Now build and run the application. After the app launches, the first thing you should see is a Salesforce login form via OAuth.

As part of the login process, you probably will receive a 2-factor login verification as you would using Salesforce in the web browser. Complete the 2-factor login as usual.

Finally, the Salesforce OAuth process will ask the user to permit the custom application to access Salesforce objects and functions on behalf of the user. These permissions are configured when creating the Connected App in the Salesforce Admin console.

Now that all that is done, the magic should happen! Our native Swift iOS app will send a SOQL query to the Salesforce back-end, and retrieve the account list, displaying it in a table view.

If your account list displays, then congratulations! You’ve managed to create a native application that accesses Salesforce data.

Download the source code for the iOS app built for this article from my GitHub repository.

Evaluating mobile projects to make the right bets

Over the years I’ve developed a specific methodology to pick the best bets from the many possibilities I see. I look at new mobile ideas and opportunities by validating them with this set of five questions.

Over the years I’ve developed a specific methodology to pick the best bets from the many possibilities I see. I look at new mobile ideas and opportunities by validating them with this set of five questions:

Would the user experience be awesome?

Users (a/k/a customers) will be the final arbiters of whether our solution is good or not. History informs us that, in the long run, we can’t force a specific user experience down our users’ throats. When we try, they seek out alternatives and leave us behind. PCs replaced mainframes because users insisted on a different user experience. Laptops replaced desktops (at a higher cost per user mind you) because users wanted more mobility. Mobile replaces laptops where users want an ultraportable solution and/or all-day battery life. Building solutions that users actually want to use is much more likely to lead to a successful project.

Is this solution adequately disruptive?

I see a lot of mobile solutions that have no legitimate reason to exist. A 15″ screen with a keyboard and mouse still is the best form factor for some solutions. For others, the desktop experience isn’t optimal but was used out of habit (or standardization, which is often nothing more than a formalized habit). Generating excitement for changing how a process is done — such as moving the form factor to mobile — is a lot easier if the new process is disruptive (in the progressive sense). To be most successful, the mobile solution should completely reinvent the process and change way the stakeholders think the process should be done.

Is this something that can only be done using mobile?

Building on point #2, we might find that not only can mobile be disruptive to the process being met, but perhaps there has been no other way to apply technology to the process before. Processing a car return to 100% completion even before the customer has been able to remove her luggage from the trunk is a great example. Prior to mobile POS, the customer either returned to the counter, or left not knowing what the final charges would be (with the resulting irate phone calls to the call center later).

Can we add value with features that are specific to mobile devices?

Sometimes we might not be solving a problem that was impossible without mobile technologies, or we might not be reinventing the process. If not then do we have the opportunity to take the business solution to a much higher level using features that existing technologies don’t offer? If we knew the location of the user, would that change the game? Would a user’s proximity to other users or to our products/services provide entirely new opportunities to serve them? If we used device sensors (e.g. GPS, accelerometers, microphones, cameras), would we create a much better solution or user experience?

How can this be funded?

Users have been conditioned by the public app stores to obtain most of the mobile software they use at no cost. This is in stark contrast to how consumers were conditioned on PC platforms in the past. Almost all PC-based software was purchased by users, and they paid for periodic software updates. In that kind of environment, we need to consider how a project will be funded. If we add a mobile “feature” to an enterprise product with no incremental cost to the user, will that drive sales or customer retention sufficiently to show acceptable ROI? If we develop something entirely new, how will users pay for the cost to provide the software? Will they pay for the software directly, pay for the back-end services the app enables, or will we recover the costs by advertising? Good ROI is possible, but requires more planning than in the past when software revenue was more transactional than it is today.

Developing Robot Runner.app for the Apple Watch

The news on Apple Watch ordering day when I rose at 6:30 US/Eastern was that the first production run had sold out — which I expected. Unexpected was that I found one (and only one!) style available for first wave delivery. The watch arrived April 24 (Friday) via UPS as promised.

The news on Apple Watch ordering day when I rose at 6:30 US/Eastern was that the first production run had sold out — which I expected. Unexpected was that I found one (and only one!) style available for first wave delivery. The watch arrived April 24 (Friday) via UPS as promised.

Time to Code!

On Friday I enjoyed using the Apple Watch, and realized that this really is a product the world needs. But by Saturday the only thing on my mind was what to code for the Watch!

What’s Robot Runner?

Robot Runner is one of my internal test apps. I use it for working with Bluetooth techniques. It’s a fun app since it has sensors, animation and involves some hardware hacking with an Arduino module and breadboard.

Robot Runner is an iPhone app written with Swift in XCode that connects to an embedded controller (the Arduino board) using Bluetooth Low Energy (a BLE shield attached to the Arduino). The architecture of the app is in the diagram below.

The iPhone app starts and stops the robot, and reads temperature and ambient light intensity sensors on the robot. It’s a good hacking solution since it incorporates many different elements used in mobile connected device applications.

Robot Runner Apple Watch Design Objective

For the Watch project, the objective is to add a to the existing app the ability for the user to connect to the Robot using the Watch instead of the iPhone. This is a typical use case for the Apple Watch — giving the user the ability to use the core functions of the app from the watch. The final architecture will be as follows:

Currently, all 3rd-party apple Watch apps are built as extensions to iPhone apps. In the diagram above, it’s not (yet) possible to eliminate the iPhone entirely, but it is possible to leave the phone in standby (in a pocket or purse, or in the next room) and let the watch wearer still use the app functions.

The Watch app remains connected to the iPhone through a Bluetooth “umbilical cord”. In MVC terms, the Models and Controller are still resident in the phone, and only the View is resident on the watch. Maybe that will change in the future, but for now, it makes sense. Leaving the Controller on the iPhone certainly will conserve the watch’s battery and CPU.

Software Architecture

A significant part of Robot Runner is the code to scan for the Bluetooth devices, connect to them, and once connected send commands and read sensor values. In the current iPhone app (Robot Runner.app, in purple within the below diagram), all of the code used by the iPhone app is contained within the single iPhone app target.

The Watch app (Robot Runner WatchKit.app, in blue), won’t connect directly to the Arduino module’s Bluetooth interface, but will do so via the Robot Runner WatchKit Extension.app (green), which runs on the iPhone. So far so good. But there’s a wrinkle that requires some re-architecting.

Once the Apple Watch is added to the solution, the two Bluetooth modules (BTDiscoverySvc.swift and BTPeripheralSvc.swift) will need to be used by Robot Runner.app and Robot Runner Watchkit Extension.app. However, although these apps are installed together, they run in different sandboxes. So, we either need to compile and link the two Bluetooth swift modules into both targets, or break them out into a common framework. The framework is easier to maintain and reduces the runtime footprint, so I chose that path. This framework is called RobotRunner.framework.

This sandbox separation also restricts sharing of data between the Apple Watch and iPhone controllers. Specifically, the project needs to have a single app group with entitlements granted to both the iPhone app and Watch Extension targets. Using the app group, the iPhone app and watch extension can share data using flat files, Core Data/SQLite and/or NSUserDefaults. Robot Runner does’t need a shared data capability (yet), so this wasn’t a factor in this project.

Putting the pieces together

With the refactoring of common code into the framework, the rest of the development is straightforward. The logic to connect to and communicate with the Robot’s Bluetooth controller was expressed in the Robot Runner WatchKit Extension.app, and the UI was designed in the Robot Runner WatchKit.app.

I’m happy to report that no significant challenges were encountered. There are differences between UIKit used for the iPhone UI and WatchKit used for the Watch UI, and the controller lifecycle states are named differently (and there are fewer of them). So, certainly, there’s a learning curve for existing iOS developers.

I expected challenges with the Core Bluetooth modules and delegates (either because of the WatchKit controller or the re-factoring into the Framework), but I was pleasantly surprised not to encounter any unusual challenges. A little bit of change related to the framework refactoring, but overall all of the Core Bluetooth code worked as-is.

The Final Results

Here’s a side-by-side (or over/under if you’re on a phone device) comparison of the UI for the iPhone and Apple Watch versions of Robot Runner. Note that in moving from the 4.7″ iPhone screen to the 38mm-42mm watch screen there has been no loss of functionality.

All of the same information is displayed. The command button and sensor outputs are still on the same screen together. Even the animated Robot renders exactly the same using the same frame images (he runs when the robot is in a run state, and is stopped when the robot is in a stopped state).

Conclusions

Apple has done a great job of keeping the basic developer workflow relatively consistent with WatchKit. Learning WatchKit isn’t much more challenging than learning any unfamiliar framework. No doubt this relatively modest learning curve has something to do with the App Store having so many apps ready-to-go on the day the Watch first shipped (reports indicated there are already thousands!).


Originally published at rekerrsive.ghost.io on April 27, 2015.

Why do iPhone Apps need Apple Watch extensions?

How often do you look at your iPhone? As reported by The Daily Mail in 2004, Marketing agency Tecmark found the average user reaches for their smartphone an eye-popping 1,500 times per week! Other studies have reported similar statistics — the Kleiner Perkins Caufield and Byers 2013 Internet Trends Report found a similar statistic — smartphone users may use their phones 150 times per day!

How often do you look at your iPhone? As reported by The Daily Mail in 2004, Marketing agency Tecmark found the average user reaches for their smartphone an eye-popping 1,500 times per week! Other studies have reported similar statistics — the Kleiner Perkins Caufield and Byers 2013 Internet Trends Report found a similar statistic — smartphone users may use their phones 150 times per day!

What does this have to do with the Apple Watch? Or any other connected smart watch for that matter?

Simply this: much of this repeated device usage is “glancing”. How often do you grab your smartphone only to glance at it? Maybe to check the time. Maybe to check if the push notification you noticed is important enough to read immediately.

I don’t “stare” at my iPhone 150 times/day. You probably don’t either. But do I “glance” at it 150 times a day? Probably. You might too (even if you don’t realize it).

The point?

Many who fail to see value in the smartwatch concept rightly conclude that a wristwatch is a poor replacement for a 4–5 inch smart phone screen. No doubt this is true.

But the question isn’t whether smartphone users will replace their phone with a smart watch (they won’t!). The question is whether smartphone owners will wear a smart watch to enable them to glance at bits of information without the need to fish out their smartphone 150 times per day.

I bet many of them will. And when they do, will your app be part of this new way of using mobile devices? Or will your users switch to an alternative that works with their watch?


Originally published at rekerrsive.ghost.io on April 26, 2015.