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.

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.

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.

Adding a MKPolyLine overlay using Swift to an iOS MapKit Map

One of the features mobile users love is to see information conveyed right on a map surface. Weather, driving directions and customer locations are just more richly explained when superimposed on a map.

One of the features mobile users love is to see information conveyed right on a map surface. Weather, driving directions and customer locations are just more richly explained when superimposed on a map.

In this post I’ll walk through the steps to draw a MKPolyLine on a MapKit map using the Swift programming language. PolyLines are useful in many scenarios:

  • Tracing driving or walking directions
    Showing the outside edge of a political boundary (e.g. a city or state)
  • Drawing a border around some other map annotation

The methodology for drawing PolyLines in recent versions of iOS has changed, so that the older MKOverlayView methodology is deprecated beginning with iOS 7, and the newer MKOverlayRenderer technique is now preferred (and when using Swift is required).

Let’s look at the process by talking through a UIViewController class that draws a PolyLine overlay. This class is very simple so that it just illustrates the technique with the most simple code possible to draw a static line over a default map.

import UIKit import MapKit class SimplePolylineViewController: UIViewController, MKMapViewDelegate {

In Line 2 above we import the MapKit framework, and at the end of line 5 declare that our class conforms to the MKMapViewDelegate protocol. This protocol is what ensures our viewForOverlay function will be called appropriately (defined later).

@IBOutlet var map : MKMapView! override func viewDidLoad() { super.viewDidLoad() createTestPolyLine() } func createTestPolyLine(){ var locations = [ CLLocation(latitude: 32.7767, longitude: -96.7970), /* San Francisco, CA */ CLLocation(latitude: 37.7833, longitude: -122.4167), /* Dallas, TX */ CLLocation(latitude: 42.2814, longitude: -83.7483), /* Ann Arbor, MI */ CLLocation(latitude: 32.7767, longitude: -96.7970) /* San Francisco, CA */ ] addPolyLineToMap(locations) }

Line 1 is the outlet that connects the class back to the MKMapView placed on the form using Interface Builder.

In viewDidLoad, we call a routine to create a test PolyLine. The PolyLine can be created or removed at any time (it doesn’t have to be in the viewDidLoad). In this example, I’ve simply added a PolyLine that draws a triangle between three US cities.

The createTestPolyLine routine defined on line 8 simply creates an array of CLLocation, and then passes that to the addPolyLineToMap function (defined below).

func addPolyLineToMap(locations: [CLLocation!]) { var coordinates = locations.map({ (location: CLLocation!) -> CLLocationCoordinate2D in return location.coordinate }) var polyline = MKPolyline(coordinates: &coordinates, count: locations.count) self.map.addOverlay(polyline) }

This routine accepts an array of CLLocation, and uses the .map routine to iterate over the location array to generate the array of coordinates expected by MapKit’s addOverlay function.

At this point we’ve done all the work we need to to add the PolyLine to the Map. But the Map still hasn’t drawn our PolyLine (it just knows we want it). Later, when the Map is ready to display our line, it will callback the following routine, which will return a PolyLineRenderer. Since we’ve only added one object to the form, it will only be called once in this case.

func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! { if (overlay is MKPolyline) { var pr = MKPolylineRenderer(overlay: overlay); pr.strokeColor = UIColor.redColor().colorWithAlphaComponent(0.5); pr.lineWidth = 5; return pr; } return nil }

And that’s it! At this point we’ve supplied everything we need to do in code to define and display a PolyLine on a MapKit map using Swift as the development language.

Here’s what the program’s output looks like:


Originally published at rekerrsive.ghost.io on February 22, 2015.

Tutorial: Using Amazon AWS S3 storage with your iOS Swift App

While the Amazon Mobile SDK documentation is very complete, it can be confusing for someone getting started. Like any backend service, AWS has a lot of moving parts, and you need to get them all working together before your app works.

While the Amazon Mobile SDK documentation is very complete, it can be confusing for someone getting started. Like any backend service, AWS has a lot of moving parts, and you need to get them all working together before your app works.

This tutorial will get you started using Amazon AWS by building an iOS app using XCode 6 and Apple Swift that reads data from the AWS S3 (Simple Storage Service). Of course your production app will need to do much more than this, and all of those other function points will build on the setup we’ll do in this tutorial. Ready? Let’s get started!

Overview of the process

To have your app up and running reading from S3, there are a few things you need to do. The first is to create an Amazon developer ID. I assume you’ve done this already, but if not, head over to the Amazon AWS developer home page, and click the orange Try AWS for Free button at the top-right of the page. Then come back to this tutorial so we can get started.

Here’s a summary of what we’ll do in this tutorial to get things working:

  • Create an S3 Bucket
  • Upload some images into the S3 Bucket
  • Create a Cognito Identity pool for the app to use
  • Use IAM to authorize the app to read from the S3 bucket
  • Setup our XCode environment to use the Amazon Mobile SDK for iOS
  • Code the app so it can access the AWS S3 bucket via the SDK

It sounds like a lot of steps (and it is!). But just follow along, and you’ll have an app working against AWS in no time!

Amazon S3 works a lot like a cloud-based file system. The basic unit of storage you’ll use is a “Bucket”. A bucket is analogous to a hard disk volume. Typically you create a bucket to store data for your application. You can also create folders within buckets. You can’t create buckets within buckets, though — just as you can’t create hard disks within hard disks.

User authorizations are created against the bucket, and we’ll create a single authorization policy for all users of the tutorial app. In this application we’ll create a bucket, and store some images in the bucket (without folders). Our app will be authorized to access the images via a Cognito identity pool.

Create an S3 Bucket

First head over to the AWS Management Console, and click on the S3 link under Storage and Content Delivery.

In the popup window, provide a unique Bucket Name for the bucket, select your preferred AWS Region, and then click on the Create button.

The Bucket Name you select must be unique among all users (not just within your own account). You can prepend the bucket name with characters that are specific to your company to make it less frustrating to create unique names.

With the bucket created, let’s upload a few images to use in our application. From the S3 console, click on the name of the bucket you just created, and then click on the Upload button.

Next select a file from your computer to upload and save it. I’ve uploaded a single image to the S3 bucket. After you save the file, it will be in the S3 bucket list, as below.

At this point we have a bucket with a file to display in our iOS app. Next we need to create an authorization using Cognito so the mobile app will be able to read the file from the bucket.

Cognito is the AWS authorization facility used to provide remote application authentication for AWS resources. Once a user is authorized with Cognito, the Identity and Access Management service is used to map authorizations between Cognito authorized users and AWS resources.

Cognito can support both unauthenticated and authenticated users simultaneously. It can delegate authentication to various Identity systems, like Google, Twitter and your custom authentication provider to meet various requirements.

In this introductory tutorial, we’ll use an unauthenticated identity — essentially letting anyone who uses our app to access the image we put in the S3 bucket. This is common for B2C applications. Layering user authentication on top of this design can certainly be done without changing the basic design of the app.

With that introduction, let’s setup Cognito! First navigate back to the AWS Management Console, and then click the link to Cognito underneath the Mobile Services heading.

At the top of the Amazon Cognito console, click the New Identity Pool button.

On the first step screen:

  • Give the identity pool a name (which must be unique in your account)
  • Click the checkbox to allow unauthenticated identities. This will enable us to authorize our app to read from the S3 bucket without authenticating users with an authentication provider
  • Click the create pool button

If our application was to be restricted to authenticated users only, we would use the to define Public, OpenID and/or Developer Authenticated Identities sections to integrate Cognito with the authentication provider we chose to use.

On the next screen (step 2), by default you’ll create two Identity and Access Management (IAM) roles — one for authenticated users, and the other for unauthenticated users. As you can probably guess, authenticated users can have different privileges to AWS resources than unauthenticated ones. In an application like ours, we might allow unauthenticated users to view images, but only authenticated users to upload images.

The default settings on this screen are fine and the names are sensible for our purposes. Review the screen, and click the Update Roles button.

Next we need to authorize app users who use the Cognito role we created to have read access to the image we uploaded to the S3 bucket.

Head over to the IAM Management Console, click on the Roles link in the left-hand navigation, then click on the unauthenticated role you created in the previous step (in this example it’s called Cognito_s3tutorialUnauth_DefaultRole).

On the next screen, you can see the role and policies that were assigned when the role was created. By default, there is a role policy that allows user profile data to be saved.

Before going further, make a note of the Role ARN, and copy it to the clipboard, then save it in a text editor. You’ll need this later when configuring your iOS application in XCode.

Once you copy the ARN, click the Create Role Policy button to create the role that will allow reading of the S3 bucket images.

The Set Permissions form allows you to use a Policy Generator or a Custom Policy. Click the Select button to choose the former option so we can use a configuration GUI to generate the policy instead of typing in the JSON syntax by hand.

In the Policy Generator make the following selections:

  • Select Amazon S3 as the AWS Service
  • Select only the GetObject action
  • Enter the ARN for the S3 bucket we created, in this format: arn:aws:s3:::com.mobiletoolworks.s3tutorial/*
  • Click the Add Statement button.
  • After you click this button, the statement will be added to a table underneath the entry fields
  • Verify the statement looks correct, and then click the Next Step button

The next page shows you a JSON version of the policy created in the dialog box.
Click the Apply Policy button.

After you Apply the Policy, you’re returned to the role summary screen. Note the new policy you added for the application is now listed in the Policy list at the bottom of the form.

Create the XCode Project

Now that we have the AWS Backend Service created and configured, let’s create our iOS Application and configure it to read from the S3 Bucket.

Launch XCode, select File/New Project, select Single View Application, and click the Next button.

Give your project a name, set the language to Swift, choose iPhone as the device, clear the User Core Data checkbox and click the Next button.

Use CocoaPods to add AWS frameworks

Next we need to add the Amazon AWS frameworks to the XCode project. You can download frameworks and add them manually if you like, but it’s much easier to use the CocoaPods dependency manager to do it for you.

If you don’t have CocoaPods configured on your system, follow these instructions to configure your XCode environment to use it.

Create a file named “podfile” in your project root folder, and add the following lines to it:

source 'https://github.com/CocoaPods/Specs.git' pod 'AWSiOSSDKv2'

Then close XCode, open a terminal window, and navigate to the folder where you created your podfile.

From that folder, type the following command to have CocoaPods:

Now wait while CocoaPods downloads the AWS SDK (and dependencies), and configures your XCode workspace.

After the workspace is configured, note the instruction on the console that you should now open your project by double-clicking on the .xcworkspace file rather than the .xcodeproj file as you did previously.

Double-click the .xcworkspace file to re-open the XCode project. Note how CocoaPods has configured the AWS runtime libraries for you within the XCode workspace.

Since we’re using Swift, and the AWS libraries are actually Objective-C, we need to create a bridging header, and configure the project for it.

First, add a bridging header to you iPhone app. I’ve called mine “BridgingHeader.h”, but you can use any name you like.

To configure the project to use the Bridging Header, click on your iPhone app target, click on Build Settings, and search for the word “Bridging”. Then change the setting for Objective-C Bridging Header to the name you gave your Bridging Header file.

The project is now configured for AWS, so next let’s implement some code to connect to AWS, download and display the file we uploaded at the beginning!

Connecting to AWS

Since our objective is to retrieve the image file uploaded to the S3 bucket, the first thing we’ll do is put a UIImageView on the main screen’s view controller so we can display the image once we have it.

Open your Main.storyboard, drag an Image View from the Object Library on to the main View Controller Scene. Then create an outlet in the ViewController class for the UIImageView. I assume you know how to do this, so I won’t go through all the steps in detail.

Now that you have a UIImageView where the image will be displayed, replace the viewDidLoad() method with the following. Of course, this is just a tutorial — a production application wouldn’t do all of this in viewDidLoad, but this will at least let you test your AWS connection and make sure you’ve got the hang of configuring your project and can use Swift to connect to AWS services.

class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView! override func viewDidLoad() { super.viewDidLoad() // Hard-coded names for the tutorial bucket and the file uploaded at the beginning let s3BucketName = "com.mobiletoolworks.s3tutorial" let fileName = "MobileToolworks-Logo.jpg" let downloadFilePath = NSTemporaryDirectory().stringByAppendingPathComponent(fileName) let downloadingFileURL = NSURL.fileURLWithPath(downloadFilePath) // Set the logging to verbose so we can see in the debug console what is happening AWSLogger.defaultLogger().logLevel = .Verbose // Create a credential provider for AWS requests let credentialsProvider = AWSCognitoCredentialsProvider.credentialsWithRegionType( AWSRegionType.USEast1, accountId: "999999999999", identityPoolId: "us-east-1:ac328da6-63f3-4748-9b8f-25b564422968", unauthRoleArn: "arn:aws:iam::696446148911:role/Cognito_s3tutorialUnauth_DefaultRole", authRoleArn: "arn:aws:iam::696446148911:role/Cognito_s3tutorialAuth_DefaultRole") // Create a service configuration for AWS requests let defaultServiceConfiguration = AWSServiceConfiguration( region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider) // Create a new download request to S3, and set its properties AWSServiceManager.defaultServiceManager() .setDefaultServiceConfiguration(defaultServiceConfiguration) let downloadRequest = AWSS3TransferManagerDownloadRequest() downloadRequest.bucket = s3BucketName downloadRequest.key = fileName downloadRequest.downloadingFileURL = downloadingFileURL let transferManager = AWSS3TransferManager.defaultS3TransferManager() transferManager.download(downloadRequest).continueWithBlock { (task: BFTask!) -> AnyObject! in if task.error != nil { println("Error downloading") println(task.error.description) } else { // Set the UIImageView to show the file that was downloaded let image = UIImage(contentsOfFile: downloadFilePath) self.imageView.image = image } return nil } // end closure }

When you run your program, it will make an asynchronous connection to the AWS S3 service to fetch the file previously uploaded. The file will be downloaded to the iOS temporary folder, and then loaded into the Image View Controller.

There will be a delay while all this happens, and in a production application you should make sure the user experience is excellent even while waiting for content to load over the network.

We set the AWS logging to “verbose”, so you can read through the debug console to see the various things happening under the hood:

You should see the message “Download Complete” that we put into our code, as well as various status and update messages from the AWS SDK as it makes progress.

In the iOS simulator, you should finally see the image we uploaded to S3, giving a visual confirmation that the entire process worked successfully!

Whew! We made it! There were a lot of steps, but now that you’ve got the hang of configuring AWS and XCode to work together, you’re well on your way to building more apps and using more AWS services within XCode!


Originally published at rekerrsive.ghost.io on February 14, 2015.

Initial thoughts on Apple’s Swift Language

This past Monday, Apple announced that iOS developers working on native applications would have a brand new language to work with: Swift. For those doing (or have done) any iOS or OSX native development, this is the part of the presentation where they stopped checking their e-mail, sat up and paid attention.

This past Monday, Apple announced that iOS developers working on native applications would have a brand new language to work with: Swift. For those doing (or have done) any iOS or OSX native development, this is the part of the presentation where they stopped checking their e-mail, sat up and paid attention.

Haven’t I been to this rodeo before?

As I listened, I had mixed emotions. On the one hand, Objective-C certainly doesn’t have the same modern feel as, say C# or even Java — not to mention some of the even more recently designed loosely-typed scripting languages that now dominate web development. A programming language for iOS built since my college-age daughter was born, and not the outcome of an unholy marriage between C and Smalltalk actually might be worth a look!

But on the other hand, new languages often introduce complete architectural shifts that break loads of code and can put an entire ecosystem at risk. I lived through “learn a language, throw out all your code and start over” transitions from C++/VB to .NET and from Windows Mobile 6 to Windows Phone. Both were painful.

The twitter reaction

As usual in the mobile space, the initial judgments on twitter were immediate! Here are some of the favorites that streamed into my twitter feed:

Most iOS devs seemed sanguine

Some people just seemed to be having a bad day

And of course there were the “my language can beat up your language” tweets

So did apple just break the ecosystem?

What I found rather genius, actually, about the way Apple architected Swift was to build it on top of the existing LVVM compiler and ARC memory management architecture. In fact Apple announced on stage that Swift code and existing Objective-C code modules could be easily used in the same solution. I haven’t tried this, but it that’s just huge.

So, at first blush, it sounds like Apple has managed to introduce a radically simpler language without breaking the ecosystem outright. As I said earlier, I lived through the change from C++ to C#, and there was effectively no interoperability for mortal programmers. Sure, it was possible to hang on to some C++ code, but running some code in the managed space and other code outside it was just too risky for most people, and I suspect few application devs actually attempted it.

If Apple’s claims are true, the migration from Objective-C to Swift can be as swift as each programmer wants it to be. Use Swift only on new projects, or new modules — seems like that approach will work. Bringing Objective-C utility and data access code along to new projects otherwise designed in Swift? Sounds like we can do that too.

The proof is when one tries it, but so far so good.

Will this new language kill performance?

Another reason new languages make me worry is performance. I cut my teeth as an ANSI C programmer, and each move to a simpler to use language over the years has resulted in programs that have lower performance than the last language. YMMV, but that’s my experience. C++ introduced some overhead, so programs were a bit slower. My switch to VB really slowed my programs down. C# and Java with their virtual machines observing code aren’t as fast as C either, but computers are much faster than they once were, so at least on Intel Core CPUs we don’t notice the performance difference that often. But ARM CPUs aren’t Intel Core i5s, so code performance between languages is still relevant on mobile platforms.

But, if Apple is to be believed, they’ve actually managed to make code run faster when coded in Swift compared to the same code in Objective-C, and way, way faster than scripting languages. Fantastic!

How different is the Developer Experience, really?

The demo Apple did on stage was showing how to use a “Playground”, an interactive interpreter environment that reminded me a bit of LinqPad, which I find invaluable on the .NET platform.

But what wasn’t clear from the demo is this: just what this change might mean for a programmer working on an average iOS App that runs on an iPhone. What would that be like? How much relearning would there be for the average Joe or Jane iOS dev?

My “Hello, World” experience

To answer that question, I spent an evening working through a few simple programs using XCode 6 Beta and the new Swift language. I have to give a shout out to Jameson Quave, who kindly published step-by-step his own initial evaluation of Swift to build an iOS app, which I found wonderful both for reference and his commentary.

The short answer, for me, is that Swift feels like all upside, and no downside. I find the language far easier to write and read, and it feels truly modern.

Many of the archaic Objective-C syntactical constructs that were dropped from more recent languages (e.g. C#, Java) are gone from Swift as well. And good riddance…if code completion knows what syntactical elements are needed, it begs the question why the programmer needs to type them in!

I do find some syntactical elements are still different than other familiar languages mobile developers may use. For example, defining the return value of a function after the function name and parameters in a declaration feels a little weird when most languages put that syntactical element first.

func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return tableData.count }

But every language has quirks and reflects the creativity and past experience of whomever designed the language. After a few weeks I doubt I’ll notice niggles like this one.

The language is different, but the architecture is the same

I found that, overall, the structure of an iOS app in Swift and Objective-C isn’t that much different. Delegates are still delegates, API methods have the same names, etc. The way you setup a TableView still is the same as before. The procedures to wire UI in Interface Builder is exactly the same as before. The only significant difference I noticed on day one is the language syntax — which in Swift is easier and less prone to dumb syntax errors in the first place.

I have a recent analogy: This winter my 16-year old daughter took a programming class at school: VB.NET. I was confident I could be a good coach, since I use C# regularly. .NET is .NET, right? Well, yes and no. I regularly found I was giving her C# syntax that didn’t work. Did VB.NET have zero-based arrays or 1-based? Did VB.NET have a “switch* keyword, or did she need to just do cascading if/then/else? How do you end a While loop in VB when there are no code block braces? I just couldn’t remember enough about VB! I was constantly on MSDN checking syntax. But when it came to overall approach to her programs, finding the bugs that illuded her, all those skills were transferrable.

I think this is the same with Swift. We need to learn new syntax, and will refer to the syntax book a lot for a few weeks. But how programs are structured, which API method to call, basic algorithmic approaches…it seems that these big items won’t need to be relearned.


Originally published at rekerrsive.ghost.io on June 4, 2014.