Posterous theme by Cory Watilo

Filed under: Iphone

Skeleton Key Cocoaheads presentation

Here’s the contents of the presentation i gave last night at cocoaheads sydney, for anyone who’s interested. Exclamation marks are slide separators, to suit my presentation app, Impromptu (impromptuapp.com).

Also the source can be found here: https://github.com/chrishulbert/CHBgDropboxSync

Skeleton Key
====

* Dropbox
* Cryptography
* Marketing

!

Dropbox
=======

* Background sync
* Fully automatic
* Suppresses errors
* One folder, yaml files

!

Sync strategy
----

* Compare folders
* Both, same: nothing
* Both, different date: newer wins
* Different: depends on last sync state

!

Different
-------

If missing locally:

Present at last sync = it's been deleted locally, so delete remotely

Missing at last sync = it's been added remotely, so download.

!

Different 2
---

If missing remotely:

Present at last sync = it's been deleted remotely, so delete locally

Missing at last sync = it's been added locally, so upload.

!

Edge cases
----

Since the last sync data is only ever used to justify a
deletion, safe to clear it any time to avoid edge cases.

Eg clearing dropbox, linking, unlinking.

!

Cryptography
============

* Master password is validated using bCrypt
* All passwords are encrypted by AES
* The AES key is derived from the master pass using PBKDF2

!

bCrypt
------

Only used to verify the master pass, nothing else. One way
slow hash designed to not be GPU-able.

Uses JFBCrypt:
http://www.jayfuerstenberg.com/blog/bcrypt-in-objective-c

5 rounds takes ~0.1s on iPhone 4

!

Storing a password
------

    salt = [JFBCrypt generateSaltWithNumberOfRounds:5];
    hash = [JFBCrypt hashPassword:clearPassword withSalt:salt];

Store both the above strings

!

Validating
----------

    test = [JFBCrypt hashPassword:clearPassword
        withSalt:salt];
    valid = [test isEqualToString:hash];

!

PBKDF2
------

An industry-standard (eg OpenSSL) way to derive a key
from a passphrase/word.

Using Security framework, and CommonCrypto/CommonKeyDerivation.h

We're making a 32byte / 256bit key.

!

Calibrating
-------

So that we know how many rounds to make it take ~0.1s:

    int rounds = CCCalibratePBKDF(kCCPBKDF2,
       clearPassword.length, keySalt.length,
       kCCPRFHmacAlgSHA256, 32, 100);

!

Salt
----

    - (NSData*)generateSalt256 {
        unsigned char salt[32];
        for (int i=0; i<32; i++) {
            salt[i] = (unsigned char)arc4random();
        }
        return [NSData dataWithBytes:salt length:32];
    }

!

Deriving
-----

    NSData* myPassData = [clearPassword
        dataUsingEncoding:NSUTF8StringEncoding];

    unsigned char rawKey[32];
    CCKeyDerivationPBKDF(kCCPBKDF2, myPassData.bytes,
        myPassData.length, keySalt.bytes, keySalt.length,
        kCCPRFHmacAlgSHA256, rounds, rawKey, 32);
    return [NSMutableData dataWithBytes:rawKey length:32];

!

AES
---

Also using Apple's Security framework's CommonCrypto

Using NSData+CommonCrypto helpers:
https://github.com/AlanQuatermain/aqtoolkit

!

Encrypt
---

    - (NSString*)encrypt:(NSString*)clear {    
        NSData* clearData = [clear
            dataUsingEncoding:NSUTF8StringEncoding];

        NSData* crypto = [clearData
            AES256EncryptedDataUsingKey:key error:nil];

        return [crypto base64EncodedString];
    }

!

Decrypt
----

    - (NSString*)decrypt:(NSString*)crypto {
        NSData* cryptoData = [NSData
            dataFromBase64String:crypto];

        NSData* clearData = [cryptoData
            decryptedAES256DataUsingKey:key
            error:nil];

        return [[NSString alloc] initWithData:clearData
            encoding:NSUTF8StringEncoding]; 
    }

!

Marketing
----

* Nobody responds to requests for reviews.
* Ads driving people to your promo-site costs more than income.
* Promo site with videos, screenshots, and features.
* Sells best when free!

!

So I got some advice..
---

Patio11 (HN)

!

Next time
----

* Find popular forum
* Working with them, make app
* Make placeholder page, collect emails, have shareables
* Determine if worth proceeding
* Attract via forums and ads
* Emails with updates
* Done
* Post launch, still interact, and email updates
* Emails link to forum for discussion

!

Please visit
-----

App: SkeletonKeyApp.com

Presentation: splinter.com.au

CHBgDropboxSync - Dropbox auto-sync for your iOS apps

Just open sourced a new project, you can grab the code and read the full docs here: https://github.com/chrishulbert/CHBgDropboxSync

CHBgDropboxSync

Obj-C / iPhone / iOS library for background syncing the contents of a folder to Dropbox, just like the ‘magical’ way that the desktop version automatically keeps everything in sync, by Chris Hulbert – chris.hulbert@gmail.com

CHBgDropboxSync

Performs a 2-way sync process designed to either download or upload changes as necessary. Uses the NSUserDefaults to keep track of local files to help it decide whether to delete or transfer if a file is present one one side but not on the other.

To use this, add the Dropbox API to your app as you normally would, creating an interface to link (and unlink) as normal. Use this class to sync a local folder (typically your Documents folder in an iOS app) to your app’s folder on Dropbox in the background without user intervention.

Github

Again, all the code’s on github: https://github.com/chrishulbert/CHBgDropboxSync

Another app marketing idea

One more idea I gleaned from tim ferris' blog, I really should keep track of these:

* Make a freemium app, with an IAP to upgrade
* Freemium means it's easy to get people 'in the door' so to speak
* Once they're 'in the door', pop up a nag alert every now and again (eg every 5th launch) to suggest why they should upgrade to the full version
* Each nag alert, recommend a different benefit of the full version, so gradually it'll convince them to purchase.

Sounds reasonable to me. It all seems to be about having a 'smooth funnel' - eg on your app's promo site, don't try to convince them to buy it, make it a smaller step: ask for their email instead. Make the app free, so it's a small step from finding it to installing it. And once they're in the app, gradually convince them into purchasing the full version with 'nag' alerts.

Of course, nag politely, don't put people off ;)

Sweet grouped tables on the iPhone

Sweet grouped tables on the iPhone

I’m a big fan of using grouped table views whenever I need to display a bit of simple information in an app. I’ve used this in at least one of my apps off the top of my head, plus another that’s in the works. You can have a look at the screenshots attached to this post to see what i’m talking about. If you like the style and want to reproduce it in one of your apps, here’s how it’s done:

Concept

Here’s the gist of it: a textured background, with black ‘embossed’ group headers, dark transparent cells with black borders and white text. There’s probably cooler designs out there, but for a designed-by-the-programmer app it looks just fine :)

(download)

Helper

I’ve got a ‘helpers’ class that I use for styling these grouped table views (and other stuff too), here’s the code you’ll need from it:

Using it

In your viewDidLoad, apply the style to the table view:

[Helpers styleTableView:vl.tableView];

The above removes the etched borders from the cells, makes the cell borders solid black, and sets the textured background using ‘backgroundView’ - it took me ages to realise that I had to use that instead of backgroundColor, so take note.

You’ll need to override the heightForHeaderInSection function:

-(CGFloat)tableView:(UITableView *)tableView

    heightForHeaderInSection:(NSInteger)section {

    return [Helpers styledTableHeaderHeight];

}

Before the cells are displayed, you must style them to override the default colours:

- (void)tableView:(UITableView *)tableView

    willDisplayCell:(UITableViewCell *)cell

    forRowAtIndexPath:(NSIndexPath *)indexPath {

    [Helpers styleWillDisplayCell:cell];

}

To set the group headings, you must use the viewForHeaderInSection instead of titleForHeaderInSection, and use the helper to position a label inside a view:

-(UIView *)tableView:(UITableView *)tableView

    viewForHeaderInSection:(NSInteger)section {

    if (section==0)

        return [Helpers styledTableHeader:@"Details"];

    if (section==1)

        return [Helpers styledTableHeader:@"Content"];

    if (section==2)

        return [Helpers styledTableHeader:@"Tweet"];

    return nil;

}

And that’s it - you’ll have a nice, simple styled grouped table view that’ll hopefully make your app look a little less plain vanilla.

 

Another app marketing idea...

One more idea to add to the mix:

* Before even *thinking* about starting development, make a landing page to collect email addresses for people who'd be interested
* Send people to these landing pages via google/facebook/forum threads
* Make a few of these landing pages
* The landing page that gets the best conversion rate (visitors vs number of emails collected) is the app that gets built!

Quickly check for any missing retina graphics in your project

Quick bit of code to throw in your app delegate as a test for any missing retina assets. Useful when checking if you’re all set for the retina iPad:

// Figure out which images don't have an @2x
NSArray* files = [[NSBundle mainBundle]
    pathsForResourcesOfType:@"png" inDirectory:nil];
for (NSString* file in files) {
    if ([file rangeOfString:@"@2x"].length==0) {
        NSString* retina = [file
            stringByReplacingOccurrencesOfString:@".png"
            withString:@"@2x.png"];
        if (![files containsObject:retina]) {
            NSLog(@"Missing retina: %@", [file lastPathComponent]);
        }
    }
}

Skeleton Key Password Manager with Dropbox

I'm in the process of submitting my latest app: Skeleton Key Password Manager with Dropbox. It should be out in 2 weeks (~16 april), assuming it gets approved.

Update: It's released (a week earlier than i expected - thanks, apple!)

Here's a bit of a sneak peek, in the form of a couple of screenshots.

(download)

Promoting apps presentation slides

Here are some slides from a presentation I recently gave about promoting iPhone apps.

If you’re wondering, the format is as per my impromptu app (impromptuapp.com). Or you can just read it as-is (it’s just markdown with exclamation marks for slide separators).

Hope someone finds this useful! It’s a conglomeration of bad knocks, and advice from some very good marketing guys who were so kind to me.

App promotion
=============

Here's a bunch of my apps, how they're going, and
how I tried to promote them.

!

Telstra app
-----------

* No marketing
* Making slightly more than pocket money
* Dying due to reviews
* Telstra site = very hard to work with
* Succeeded because people already searching for it

!

Impromptu
---------

* Made app
* Made website to promote it
* Use ads to send people to website
* Not much luck

!

Service History
---------------

* Made app
* Made website to promote it
* Made all other apps free
* Made the 'more apps' tab promote this app
* Get 2 or 3 sales a day - so it is working, a bit
* Not much luck

!

Skeleton Key
------------

* Made app
* Will have site
* Asked for marketing help, and got...

!

Suggestions!
---

* Landing page site
* Collect emails, not send to app store
* Getting emails is easier than getting sales
* Then promote the app through emails, leading to sales
* Send people there via ads, forums (ads don't work)
* But i've already built it, so i'll try this for the next app...

!

Patio11's suggestions
-------

* Find a community
* Build their app
* Work with them
* Then marketing is easy

!

My new idea
-------

Combine both, to hopefully great effect

!

New Method
==========

* Find underserved community forum
* Working with them, make app
* Make placeholder page, collect emails, have shareables
* Attract via forums and ads
* Emails with updates
* Done
* Post launch, still interact, and email updates
* Emails link to forum for discussion

!

Scratch your own itch is wrong, scratch a community's itch.

How i just wasted a month on my latest app, and how you don't need to

I just wasted a month of my life. I’ve been working on an iPhone app (a password manager like 1password/lastpass but competing on price), thinking it was a brilliant idea, and now it’s come time to market it. Having seen Patrick McKenzie’s open invitation to send him emails, I thought i’d give him a try. Anyway, a couple of succinct emails later, I now realise what a fool i’ve been. (Props to Patrick for being so helpful, though!)

Basically, I got things the wrong way around: I wrote an app, got it ready to ship, and then thought ‘now, time to sprinkle a bit of marketing on top’. But what is now clear to me, is that the marketing should have come first. In fact, the customers should have been in the drivers seat the whole time. In hindsight, its a little obvious.

Lets call this ‘MDD’ – Marketing Driven Development. Or, maybe People Driven Development? I like that more, it sounds a little less like an MBA term… The idea being, that you find a bunch of people who want an app, and make it for them, keep them updated as you work through the development process, get their feedback as you go (basically just keep them involved), then once it’s done your marketing is pretty much already done. Plus, you might have made a few more friends along the way.

So, going forwards, my strategy is going to look like this:

  • Don’t roll my eyes (not that i currently do, anyway) when friends suggest an app idea that is obvious to me, saying i’ve already got plenty of ideas. Realise that my ideas suit a very small audience: people like me. Listen to their ideas.
  • If its a good idea, look for a popular internet forum for that kindof thing, where the moderators are friendly to commercial types getting involved (a lot aren’t – I’m looking at you, whirlpool).
  • Start a thread, talking to people about the app idea, show a couple screenshot mockups, and see if anyone is interested
  • If i get, say, 5 people say ‘i’d buy that!’, crack open Xcode and get busy
  • Post updates and questions and requests for opinions ongoing. Get people involved. Take their feedback. Get them excited about how they can influence the direction of the app.
  • Launch the app free for a week, get them to install it, and ask them to write nice reviews. Make it free, with IAP to unlock pro features.
  • Hope for the best.

Anyway, i’ve now got an app with no prospects of finding a community who’ll want it. All because I developed what I thought was a good idea, but will certainly struggle to find anyone who’ll want it. I should have started with what people want first. Still, i’m happy to learn a lesson the hard way rather than not at all.

So, next time you start work on a project, find a community forum where lots of people want it. Or at least 5 people who promise they’ll buy it if you build it.