Category: Mobile

App development for mobile devices such as iPhone and Android.

Static Table View Containers

Static table views are the most straight forward way of laying out a list of items using Storyboards in Interface Builder. (You are using Storyboards by now right?) These type of table views are better suited for a static list of items like a menu or settings screen inside of your app. One of the limitations with this type of table view cell is that it requires a UITableViewController inside of your storyboard. This could be problematic because of how table view controllers intrinsically take over an entire screen worth of content.

An approach to get around this limitation is to use view controller containment within your storyboard. By doing this, you are essentially defining a content area for which your table view controller will be placed. Using a container gives the ability to layout your static cells alongside your parent view controller.

Start by dragging a container view onto your view controller where you want your table view to appear. Go ahead and delete the new ViewController that gets created and instead place a UITableViewController in your storyboard. Now control + drag in Interface Builder from your container view onto the new UITablVeiwController and click on the embed option.

EmbedSegueMenu

If you do this correctly, your tableview will take on the dimensions of your container view giving you a good idea of its layout in relation to other views on the screen.

StaticTableViewIB

Now you have the flexibility of adding cells at design time without the need for boilerplate datasource logic associated with prototype cells.

Learn more about static table views from the WWDC session.

More

Apple Pay with iPhone 6 in a nutshell

With the announcement of iPhone 6 comes a unique way of paying for products using a combination of the NFC antenna and Touch ID. Apple accelerated the popularity of portable MP3 players with the introduction of iPod and in a similar fashion it appears as though Apple is well positioned to bring “contactless payment” into the mainstream. Due in part because of how the majority of iTunes accounts already contain a form of payment, it can be easily added as the default payment method in PassBook for owners of iPhone 6 or the Apple Watch beginning in early 2015.

Timing

Apple is actually fairly late to the game when it comes to this method of payment. Competitors like Google Wallet and PayPay already have a presence in this space but not without opposition from carriers who have been in favor of their own solution.

A cause of concern up until now has been the cost for merchants to update their card readers to accept NFC based payment technology. The timing of the Apple Pay announcement comes only a year before the new EMV requirements on card readers goes into effect in October 2015. It seems likely that merchants will choose to upgrade their readers to support both EMV and the NFC contactless payment method used in Apple Pay.

NFC Reader Logo

NFC Reader Logo

Security

When you are authorized via Touch ID, a payment token is generated from the Secure Element inside your phone via the PassKit Framework that is used to complete the transaction by the payment processor. With Touch ID, your credit card and forms of identification never exchange hands.

When a credit card is added to PassBook, a device specific account number is stored in place of the credit card number in the secure element. If you were to misplace your phone, you can suspend payments from that device from the Find My iPhone web interface.

Developers

Of course for us developers there is a way of building Apple Pay into our iOS apps. The PassKit framework provides API’s for creating a payment token as well as presenting the payment sheet that contains shipping / billing info and shipping method.

The PassKit Framework Reference has details on the classes necessary to accept Apple Pay in your app.

Apple is adamant about how they are not in the business of collecting your information. They are simply providing us with a simplified purchase experience. Apple Pay will be available starting in October when 220,000+ stores across the US begin accepting it as payment.

More

Getting started with UI Automation in Xcode 4

Did you know that with a little patience and some knowledge of JavaScript you can write automated UI tests against your iOS applications? What’s even better is with Xcode 4.2 installed its as easy as clicking a record button and having Instruments generate the test scripts for you.

For this tutorial I’m going to download the Core Data Recipes application from Apple’s developer website. Once you’ve opened the app in Xcode go ahead and click on
Product -> Profile in the menu bar (command + I works just as well) to launch the Instruments tool that we’ll be using to run our tests with.

You should see your application launched in the simulator along with a running instruments profiler. Form here you’re going to want to check that the Automation instrument has been created and then click on the Add button just below it to create a new Automator script.

After clicking on Add -> Create you will notice a record button looming towards the bottom that when clicked allows you to begin interacting with your application and generating the JavaScript necessary to automate the test.

Here’s a trivial example that I recorded using the sample application to demonstrate.

var target = UIATarget.localTarget();

target.frontMostApp().mainWindow().tableViews()["Empty list"].cells()["Chocolate cake with chocolate frosting, 1 hour, Chocolate Cake"].tap();
target.frontMostApp().navigationBar().rightButton().tap();
target.frontMostApp().mainWindow().tableViews()["Empty list"].cells()["Dessert"].tap();
target.frontMostApp().mainWindow().tableViews()["Empty list"].cells()["Snack"].tap();
target.frontMostApp().navigationBar().leftButton().tap();
target.frontMostApp().mainWindow().tableViews()["Empty list"].cells()["Snack"].tap();
target.frontMostApp().mainWindow().tableViews()["Empty list"].cells()["Dessert"].tap();
target.frontMostApp().navigationBar().leftButton().tap();
target.frontMostApp().navigationBar().rightButton().tap();
target.frontMostApp().navigationBar().leftButton().tap();

Having Xcode generate the script for you can test your patience with how it tries to target certain elements incorrectly but often times it will at the very least get you a good base to work from if you’re just getting the hang of how to ineract with your app.

It’s worth mentioning that this script will run just fine if you are dealing with UI elements that stay the same across test runs or otherwise remain static. If this isn’t the case then you may run into cases where elements have different attributes or no longer exist if you were to delete a row in a UITableView for example. This is where some knowledge of JavaScript (and the UI Automation Reference) comes in handy to check the existence and state of elements. This is beyond the scope of this article but one possible approach to this problem would be to restore your data prior to each test run.

You’ll notice that the third line has the cell contents hard coded into the script which is just another way of gaining access to it.

target.frontMostApp().mainWindow().tableViews()["Empty list"]
    .cells()["Chocolate cake with chocolate frosting, Chocolate Cake"].tap();

Thankfully we have a couple of much better options to achieve the same result. The first way is by using the element placement index inside of the cells array.

target.frontMostApp().mainWindow().tableViews()["Empty list"]
    .cells()[0].tap();

You can alternatively set the accessability label through Interface Builder.

The accessibilityLabel property can also be set at runtime if you so choose, this is most useful for dynamic layouts.

cell.isAccessibilityElement = YES;
cell.accessibilityLabel = @"Cake";

Given the nature of the Core Data Recipes sample application our best approach would be to use the cell index or full cell label text for demonstration purposes. Ideally the accessibility text would be part of your data source in some fashion so in code we could iterate over the data while creating the table view cells.

Taking another look at the script you can see a lot of repetitive ways of accessing elements, we can pull out some common pieces and have cached versions to work with instead. Not only does this make your script more readable but it will also help speed up the running times.

var target = UIATarget.localTarget();
var app = target.frontMostApp();
var window = app.mainWindow();
var navBar = window.navigationBar();

We’ll also go ahead and change the hardcoded string key to access the cell to an ordinal index value here as well by updating tableViews()["Empty list"] to be
tableViews()[0]

Now what’s left is a script that is much more maintainable going forward.

var target = UIATarget.localTarget();
var app = target.frontMostApp();
var window = app.mainWindow();
var navBar = window.navigationBar();

// Select Recipe
window.tableViews()[0].cells()[0].tap();

// Change Ingredient
navBar.rightButton().tap();
window.tableViews()[0].cells()["Dessert"].tap();
window.tableViews()[0].cells()["Snack"].tap();
navBar.leftButton().tap();

// Change Ingredient Again
window.tableViews()[0].cells()["Snack"].tap();
window.tableViews()[0].cells()["Dessert"].tap();
navBar.leftButton().tap();

// Done Editing
navBar.rightButton().tap();

// Back To Recipe List
navBar.leftButton().tap();

Where to go from here?

One aspect of the documentation that is worth exploring is the UIALogger class. UIALogger gives you the ability to define a beginning and end of your test cases and not only provide a means of structuring tests but you can record pass or fail messages to give more context to the results. These messages will get output in the Trace Log portion of the Instruments tool.

More

Blocks save the day

I’m consistently amazed how useful blocks are in Objective-C. So much so that I’ll be attempting to document useful ways that blocks can make your life easier as an iOS developer. Here’s the first of (hopefully) many posts of its kind.

Take this code

- (void)viewDidAppear:(BOOL)animated {
{
    UIView *viewToAnimate = ...
    [self performSelector:@selector(animateIt:) withObject:viewToAnimate afterDelay:1.0f];
}

-(void)animateIt:(id)sender 
{
    // animate viewToAnimate
}

It seems like this could be better by having the animation code where you have your selector delay setup. Well guess what? Blocks to the rescue!

@implementation NSObject (PerformBlockAfterDelay)

- (void)performBlock:(void (^)(void))block 
          afterDelay:(NSTimeInterval)delay 
{
    block = [[block copy] autorelease];
    [self performSelector:@selector(fireBlockAfterDelay:) 
               withObject:block 
               afterDelay:delay];
}

- (void)fireBlockAfterDelay:(void (^)(void))block 
{
    block();
}

@end

This snippet is using category that you can #import into your class. Using this in practice you get this.

- (void)viewDidAppear:(BOOL)animated {
{
    UIView *viewToAnimate = ...
    [self performBlock:^void() {
        // animate viewToAnimate
    } afterDelay:1.0f];
}

Credit goes out to this StackOverflow thread for the tip.

More

Cocoaconf 2011 Recap

Cocoaconf Logo

Cocoaconf actually took me by surprise as I just happened to hear about it from a tweet within a month of it taking place. It’s pretty rare to find developer events of this size so close by Detroit so I had to jump on the opportunity. Who would’ve thought that I would get so much out of spending a few days in Dublin, Ohio?

Cocoaconf is a brand new conference that’s geared towards a technical audience (eg: no vendors were present). There were sessions for many skill levels and even an all day “soup to nuts” workshop that created an iPhone app from scratch using many of the Cocoa API’s. The sessions that I found most helpful were ones that I don’t normally see too much coverage of like UIAutomation with tuneup_js as well as unit testing with ghunit and ocmock. I would say that the session that surprised me the most was on NSURLConnection and the different networking protocols and technologies that are present in Cocoa. Immediately I could see the benefit of things like Bonjour discovery and the AFNetworking library.

One session that I thought was unique was the “We Made An App For That” talks where attendees had the opportunity to talk about their experiences in building their app and give a demonstration of how their apps function. The apps ranged from one that had just been released within the last month and even one that had sold thirty thousand copies!

To help give the speakers feedback there were cocoa bucks being rewarded for those folks who filled out the questioners. These cocoa bucks were then entered in a drawing to win prizes at the end. This was clearly an important part of the conference as they were being handed out at all of the doors, and from the looks of things they had a good amount of them turned in. I actually didn’t realize at the time but quite a few of the books that were being given out were written by the speakers at Cocoaconf. This goes to show you the quality that was put into their debut event and from the sound of things it’s only going to be getting better.

More