WatchKit and Threading

While working on some of the chapters for the upcomming WatchKit by Tutorials book, I assumed since WatchKit extensions bascially run as a Remote Procedure Call (RPC), writing asynchronous code wouldn't work. This was a bummer because running dynamic applications on Apple Watch would be very slow.

But I hadn't actually tried it.

At Facebook we have a saying that "Code Wins Arguments", so I decided to prove that something horribly, horribly wrong would happen when you wrote async code in WatchKit.

I wrote a really simple app to test a couple of things:

  • Threading in WatchKit
  • Updating the UI after willActivate: finishes
  • Updating layout after setting contents (like setImage:)

Experiment Storyboard Setup

Inside initWithContext: I download an image and set the contents of the WKInterfaceImage. I also set the contents of the label above the image with text that will wrap, just to push the watch layout system.

[self.label setText:@"Loaded at initWithContext:"];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  NSURL *url = [NSURL URLWithString:@"http://placehold.it/120x100"];
  NSData *data = [NSData dataWithContentsOfURL:url];
  UIImage *placeholder = [UIImage imageWithData:data];

  dispatch_async(dispatch_get_main_queue(), ^{
    [self.image setImage:placeholder];
  });
});

To my surprise, the image downloaded, set the WKInterfaceImage contents, resized based on the image width and height, and pushed the label below the image down!

This worked?

Granted, this is on a simulator so we will have to see what happens when running on a real device and how the Bluetooth connection handles these async callbacks, but this is a great sign!

If you want to play with this project you can check it out on Github.

Sidenote: Yes I'm using Objective-C. Swift introspection sucks and doesn't work at all with Facebook's Chisel LLDB extensions.

The new UISplitViewController and iOS 7

Splitting all the things

tl;dr download the sample project

iOS 8 updated the UISplitViewController API to work on iPhones. It let's you specify when and how the split layout happens.

You end up with a universal storyboard which is very DRY.

However, I assumed that the new UISplitViewController only worked for iPhones running at least iOS 8.

Problem is that the iOS 8 adoption rate is really bad compared to previous versions. As of November 17, 2014 iOS 8 still has less than 60% of the market.

I thought that in order to use UISplitViewController I would have to scatter my code with OS if-statements or use multiple storyboards.

But it turns out that the new UISplitViewController APIs are fully compatible with iOS 7! Why Apple doesn't document this out is beyond me.

Yup, you can use a single storyboard with a UISplitViewController and have all of this without any compatibility checking:

  • UINavigationController on iPhone 4 with iOS 7
  • UISplitViewController with landscape split on iPhone 6+ with iOS 8
  • UISplitViewController always splitting on all iPads

There are probably even more customizations, these are just the ones that I've been playing with.

Getting it to work

This NSHipster article got me rolling with UISplitViewController. Using their pattern, you need:

  • UISplitViewController as the initial controller
  • Navigation controller as master with some controller as root (usually a table)
  • Navigation controller as detail with some controller as root
  • Something as the UISplitViewControllerDelegate

Use a Show (Detail) segue from your table cell to the detail navigation controller.

Interface Builder

In -prepareForSegue: of the master controller, you will need to check if the segue destination is either a UINavigationController (from a split view detail swap) or your detail controller (from a nav push).

var dest: DetailController
if let nav = segue.destinationViewController as? UINavigationController {
  dest = nav.topViewController as DetailController
} else {
  dest = segue.destinationViewController as DetailController
}

Finally, whatever is the delegate for your UISplitViewController needs to implement this long-ass delegate method:

func splitViewController(
  splitViewController: UISplitViewController,
  collapseSecondaryViewController secondaryViewController: UIViewController!,
  ontoPrimaryViewController primaryViewController: UIViewController!) -> Bool
{
  return true
}

Check out the sample project on Github and try it for yourself. This project has been tested on iOS 7 on all simulators and an iPhone 4 as well as iOS 8 on an iPhone 6 and all simulators.

How I Validated a Niche Idea for $32.19 with Facebook Ads

I've been itching to build a niche market product for a while now. After making tons of iOS apps, I got bored that nothing really took off. I want to make something that helps people's lives, and I want to do it so well that they'll want to pay for it.

Using the book Start Small, Stay Small as a guide, I found a niche that I could become familiar with by combing through all of my first-degree connections.

I found some valuable metrics about the niche's membership in an annual report. About 14,000 participants in this niche are paid over $3,000/year. If I could sell a $10/mo subscription to 1% of the members, I'd be pulling in $1,400/mo. That's more than enough to satisfy my itch.

I should note that I'm not shooting for the stars, I just want to build a tool that has real impact.

TL;DR on my experiment

I used Typeform and Facebook Ads to validate an idea with a niche market.

  • $32.19 spend on Facebook Ads
  • Ad reached 7,516 people
  • 240 clicks with 310 unique visitors
  • 112 surveys answered
  • 101 emails collected

Collecting Feedback

I've used Survey Monkey and Google Forms in the past for college projects, but since then I've learned a lot about user experience and wanted something more user friendly. Those tools are quick and easy to get moving, but I needed users to want to fill out the survey.

Enter Typeform.

Typeform is a newer service for building high-quality, responsive forms and surveys. I used Typeform for the first time when I user tested one of my apps. I created that survey in less than an hour.

The form builder is super simple to use and has a ton of robust features, even at the free tier.

Typeform Workflow

The question builder is even more detailed. You can add images, video, make it required, all types of things.

Typeform Detail

You can check out one of my old surveys to see how responsive and fluid the forms are. Feel free to save data if you want, I'm not using that form anymore.

You can create basic surveys and forms with Typeform for free. Upgrading gets you access to more complex workflows, like conditional user paths, and advanced data fields.

The only bummer is that you can't manage your Typeforms on mobile, including tablets. There's an API, so if I'm bored again I may whip something together.

Make sure you ask for emails at the end of your form! It's an easy way to collect emails for early adopters or beta testers.

Reaching Your Market

A survey is pointless without getting it in front of people. I'm not a marketer, and I don't really know what I'm doing. Lucky for me I attended Facebook's F8 conference this year and learned about their powerful targeted ad platform.

You can use Facebook Ads to create extremely targeted ad campaigns using age, gender, education, interests, etc. Facebook even gives you a gauge to show you roughly how many people your targeting configuration will reach.

Facebook targeting

All you need to create an ad is a Facebook Page and a URL. In my case I created a throw-away page and linked to my Typeform survey.

I filled in configured the ad towards my niche based on assumptions, and whittled my reach down to about 600,000 people. I capped my budget at $50, let Facebook determine my CPC, and checked out with my credit card (you can use Paypal too).

Results

Here are the results of my Facebook Ad with Typeform:

Facebook Results

I got my survey in front of 7,516 people and had 240 clicks all for $32.19. That cost me $0.13/click. Facebook tells me that it usually costs about $0.60/click.

I have no idea why my ad was so cheap, but that's incredibly valuable since it tells me advertising my product will be cheap.

I also ended up with 112 survey responses which included 101 emails. My questions focused around pain points, and, by analyzing the responses, I found a problem that roughly 85% of participants shared.

Typeform contains some basic analytics as well. I got a break down of my audience's devices and found that the majority of users who clicked on the Facebook Ad have smartphones.

Something really unexpected happened too, people were Liking my ad on Facebook! When a user Likes a page or ad that ad is then shared on that person's wall. Free advertising. Facebook reported 240 clicks while Typeform reported 310 unique visitors.

Hindsight

I spent more time on my survey questions than actually building the survey, which is fine, but I really wish I spent even more time on creating the right questions. I could have vetted the questions with my personal network before sending them into the wild.

I also ran the ad for a month which was way too long. I could have just as easily ran it for a week. This likely would have raised my CPC, but if that meant getting things over and done with sooner, that's fine.

Conclusion

I highly recommend using Typeform (or any survey tool) with Facebook Ads next time you have an idea or market that needs validating or testing. It's just too cheap and easy not to test before investing time and money building something.

For me, I spent just a pinch over $30 for some solid data. The next step is to figure out exactly how to solve the problem I found, and that's the fun part.

Note: Normally I wouldn't care about hiding an idea, since the idea is 5% of the work, but I might have actually found something.