Chris' Blog.

My occasional thoughts on iOS development, developers careers, trying to make an income from the App Store, and updates on life in general.

Swift KVO alternative

You may have noticed that KVO isn't really supported terribly well in Swift. It feels like a second-class citizen. So, inspired by ReactiveCocoa and some conversations with the uber-smart Manuel Chakravarty, I came up with the below solution which I'd like to share with you.

It's a deliberately simplified version of Reactive's MutableProperty, as I find that Reactive is a tough sell when you're part of a big team. However, it is much more approachable to introduce something small and simple like this.

Note that by prioritising simplicity, it lacks certain features such as thread-safety (which you could implement yourself if required - I generally prefer to do almost everything on the main thread). It is also not provided as a pod/carthage framework because if you brought this into your app, you really should customise it further as per your needs. Plus it's like 60 lines of code. However, all that said, it is a good replacement for KVO.

So here it is, ready for you to test-drive in a Swift playground:

class Property<T> {
    private var _value: T
    var value: T {
        get { return _value }
        set {
            _value = newValue
            tellSubscribers()
        }
    }

    init(_ value: T) {
        _value = value
    }

    var subscriptions = [Subscription<T>]()
    func subscribe(subscriber: AnyObject, next: T -> Void) {
        subscriptions.append(
            Subscription(subscriber: subscriber, next: next))
    }

    private func tellSubscribers() {
        subscriptions =
            subscriptions.flatMap(tellAndFilterSubscription)
    }

    private func tellAndFilterSubscription(subscription:
           Subscription<T>) -> Subscription<T>? {
        if subscription.subscriber != nil { // Subscriber exists.
            subscription.next(_value)
            return subscription
        } else { // Subscriber has gone; cull this subscription.
            return nil
        }
    }
}

struct Subscription<T> {
    weak var subscriber: AnyObject?
    let next: T -> Void
}

How it works

The idea is that it stores a weak reference to the ‘subscriber’ in a subscription struct alongside the ‘subscription’ block, which together goes into a ‘subscriptions’ array. The subscriptions where the subscriber = nil get culled each time it broadcasts a new value.

How to use it

Here's how you'd declare a property in one of your classes:

class UserManager {
    // Something that isn't nillable, and has an initial value.
    let username = Property("InitialValue")

    // Something that is nillable, and has no initial value.
    let nickname = Property<String?>(nil)
}

And here's how you subscribe to updates on a property. The below code will take care of freeing the block after your view controller disappears, so you don't need to worry about memory management:

class UserViewController {
    func subscribe() {
        UserManager.sharedManager.username.subscribe(self) {
            [weak self] newValue in
            self?.userLabel.text = newValue
        }
...

And before you know it, you're half-way towards Reactive coding techniques. See, that wasn't too hard was it? :)

Tests

Unit tests are great, right? Here's my approximation of them using a playground:

class Foo { // The one with the property.
    let property = Property("Blah")
}
class Bar { // The observer.
    var string: String?
}
class Test {
    var string: String?
    func test() {
        // Setup bar subscribed to foo's property.
        let foo = Foo()
        var bar: Bar? = Bar()
        foo.property.subscribe(bar!) {
            [weak bar] newValue in
            bar?.string = newValue
        }

        // Example of how to subscribe.
        foo.property.subscribe(self) {
            [weak self] newValue in
            self?.string = newValue
        }

        // Test it calls the subscriber.
        foo.property.value = "Test"
        print(bar!.string) // Should be "Test"
        print(string) // Should also be "Test"

        // Test it culls nilled subscribers.
        print(foo.property.subscriptions.count) // Should be 1.
        bar = nil
        foo.property.value = "GiveItAChanceToCull"
        print(foo.property.subscriptions.count) // Should be 0.
    }
}
Test().test()

Have a good one!


Swift Keychain wrapper

If, like most Apps, you need to store something in the Keychain, hopefully I can help you out here. This post is written because most Keychain-related cocoapods don't handle the three modern requirements:

  • Cloud sync via iCloud Keychain
  • Enabling background access for background-fetch apps
  • Swift (version 2 as of this writing)

Plus, I'm a fan of writing the minimum code that can do the job, and customising per requirements if necessary, rather than bringing in a large cocoapod with more features than you'll ever need.

Having said that, BMCredentials is awesome on the first two points if you don't mind a bit of Objective-C in your new project. Written by a friend though so i'm a tad biased ;)

Now, before we get stuck in, you should consider watching Security and Your Apps from WWDC 2015 and reading the slides, which provides the inspiration for some of this article.

All the source code including unit tests is available here: github.com/chrishulbert/Swift2Keychain.

Bridging SecItemX to Swift

The first hurdle is calling the four SecItem functions from Swift:

  • SecItemAdd
  • SecItemDelete
  • SecItemUpdate
  • SecItemCopyMatching

These functions are a C library, returning data via unmanaged double-pointers and non-enum error codes. So I'll show you how to make a slim wrapper that converts them to return values straightforwardly, and throws errors as a nicely-typed enum. Firstly, here is the error enumeration that maps from the errSecX values:

import Security

enum KeychainError: ErrorType {
    case Unimplemented
    case Param
    case Allocate
    case NotAvailable
    case AuthFailed
    case DuplicateItem
    case ItemNotFound
    case InteractionNotAllowed
    case Decode
    case Unknown

    /// Returns the appropriate error for the status, or nil if it
    /// was successful, or Unknown for a code that doesn't match.
    static func errorFromOSStatus(rawStatus: OSStatus) ->
            KeychainError? {
        if rawStatus == errSecSuccess {
            return nil
        } else {
            // If the mapping doesn't find a match, return unknown.
            return mapping[rawStatus] ?? .Unknown
        }
    }

    static let mapping: [Int32: KeychainError] = [
        errSecUnimplemented: .Unimplemented,
        errSecParam: .Param,
        errSecAllocate: .Allocate,
        errSecNotAvailable: .NotAvailable,
        errSecAuthFailed: .AuthFailed,
        errSecDuplicateItem: .DuplicateItem,
        errSecItemNotFound: .ItemNotFound,
        errSecInteractionNotAllowed: .InteractionNotAllowed,
        errSecDecode: .Decode
    ]
}

I really love how Swift allows us to place the errorFromOSStatus helper inside the enum, as well as the static mapping dictionary. Now it's worth mentioning that I tried to make the enum with the same base type as the OSStatus, and set each case's raw value to the corresponding errSecX value. However, this only worked if I used the actual integer values themselves, I couldn't use the errSecX constants, which I thought was a code smell, and instead settled on using the above mapping instead. I'll understand if you disagree.

Bridging the SecItemX methods

Next are my helpers that simply pass through to the SecItem methods, returning the result straightforwardly and throwing if there is an error. This is also a good example of how to call C functions that return data via a double pointer from Swift:

struct SecItemWrapper {
    static func matching(query: [String: AnyObject]) throws -> AnyObject? {
        var rawResult: Unmanaged<AnyObject>?
        let rawStatus = SecItemCopyMatching(query, &rawResult)
        // Immediately take the retained value, so it won't leak
        // in case it needs to throw.
        let result: AnyObject? = rawResult?.takeRetainedValue()

        if let error = KeychainError.errorFromOSStatus(rawStatus) {
            throw error
        }
        return result
    }

    static func add(attributes: [String: AnyObject]) throws -> AnyObject? {
        var rawResult: Unmanaged<AnyObject>?
        let rawStatus = SecItemAdd(attributes, &rawResult)
        let result: AnyObject? = rawResult?.takeRetainedValue()

        if let error = KeychainError.errorFromOSStatus(rawStatus) {
            throw error
        }
        return result
    }

    static func update(query: [String: AnyObject],
            attributesToUpdate: [String: AnyObject]) throws {
        let rawStatus = SecItemUpdate(query, attributesToUpdate)
        if let error = KeychainError.errorFromOSStatus(rawStatus) {
            throw error
        }
    }

    static func delete(query: [String: AnyObject]) throws {
        let rawStatus = SecItemDelete(query)
        if let error = KeychainError.errorFromOSStatus(rawStatus) {
            throw error
        }
    }
}

In short, you created a typed, unmanaged optional: var x: Unmanaged<T>?. You pass this in via the & operator. And due to the 'create rule' which applies, the returned value has a +1 retain count, which we balance by calling takeRetainedValue.

I expect that in a future version of Swift, Apple will tidy up the way that C methods such as these return unsafe unmanaged pointers to something simpler, and the above code will become shorter.

Convenience methods

Now that you've got the bridge in place, it's a matter of adding some convenience methods for typical keychain operations:

struct Keychain {

    static func deleteAccount(account: String) {
        do {
            try SecItemWrapper.delete([
                kSecClass as String: kSecClassGenericPassword,
                kSecAttrService as String: Constants.service,
                kSecAttrAccount as String: account,
                kSecAttrSynchronizable as String: kSecAttrSynchronizableAny,
            ])
        } catch KeychainError.ItemNotFound {
            // Ignore this error.
        } catch let error {
            NSLog("deleteAccount error: \(error)")
        }
    }

    static func dataForAccount(account: String) -> NSData? {
        do {
            let query = [
                kSecClass as String: kSecClassGenericPassword,
                kSecAttrService as String: Constants.service,
                kSecAttrAccount as String: account,
                kSecAttrSynchronizable as String: kSecAttrSynchronizableAny,
                kSecReturnData as String: kCFBooleanTrue as CFTypeRef,
            ]
            let result = try SecItemWrapper.matching(query)
            return result as? NSData
        } catch KeychainError.ItemNotFound {
            // Ignore this error, simply return nil.
            return nil
        } catch let error {
            NSLog("dataForAccount error: \(error)")
            return nil
        }
    }

    static func stringForAccount(account: String) -> String? {
        if let data = dataForAccount(account) {
            return NSString(data: data,
                encoding: NSUTF8StringEncoding) as? String
        } else {
            return nil
        }
    }

    static func setData(data: NSData,
            forAccount account: String,
            synchronizable: Bool,
            background: Bool) {
        do {
            // Remove the item if it already exists.
            // This saves having to deal with SecItemUpdate.
            // Reasonable people may disagree with this approach.
            deleteAccount(account)

            // Add it.
            try SecItemWrapper.add([
                kSecClass as String: kSecClassGenericPassword,
                kSecAttrService as String: Constants.service,
                kSecAttrAccount as String: account,
                kSecAttrSynchronizable as String: synchronizable ?
                    kCFBooleanTrue : kCFBooleanFalse,
                kSecValueData as String: data,
                kSecAttrAccessible as String: background ?
                    kSecAttrAccessibleAfterFirstUnlock :
                    kSecAttrAccessibleWhenUnlocked,
            ])
        } catch let error {
            NSLog("setData error: \(error)")
        }
    }

    static func setString(string: String,
            forAccount account: String,
            synchronizable: Bool,
            background: Bool) {
        let data = string.dataUsingEncoding(NSUTF8StringEncoding)!
        setData(data,
            forAccount: account,
            synchronizable: synchronizable,
            background: background)
    }

    struct Constants {
        // FIXME: Change this to the name of your app or company!
        static let service = "MyService"
    }
}

Some things to note:

  • Make sure you change the service name in the Constants struct above!
  • kSecAttrSynchronizable: kSecAttrSynchronizableAny is essential in all queries because SecItem.h says: "If the key is not supplied... then no synchronizable items will be added or returned".
  • Everything is stored in the keychain as NSData natively, and you must convert to and from strings using UTF-8 encoding.
  • SecItemAdd will fail if the item already exists, so I simply delete before adding always. Other libraries take the more complicated route of checking if present, if so calling SecItemUpdate, otherwise SecItemAdd. You may prefer that.
  • Pass true for synchronizable if you want this entry to be synced to the user's other devices via iCloud.
  • Pass true for background if you'd like the entry to be used while your app is in the background, eg background fetch. Keep in mind you still won't be able to get the value if the user does a fresh reboot and hasn't launched your app yet, so you have to handle that gracefully for eg users who turn their devices off at night.
  • If you want to read more about using the keychain, read SecItem.h.
  • Source code and unit tests are available here: github.com/chrishulbert/Swift2Keychain.

Hope someone finds this helpful :)


Swift NSURLSession wrapper

If you start a new App project in Swift, you will likely sooner or later have to ask yourself: Which networking library should I use? Back in Objective-C, the common choice was AFNetworking. However, I bet you'd like a more 'Swift' option for your new project.

So you check out AFNetworking's Swift successor: Alamofire. Or any of a whole stack of new Swift networking libraries. And it is indeed quite 'Swift-y' and nice, however since it is such a new library, it is inevitably missing a few features that you need, and it'll take a while for you to customise it to talk to your backend, which (I'm willing to bet!) has a couple of non-standard quirks. Eg it always needs a special HTTP header, or it always responds with JSON however it gets the content-type header wrong.

I suggest you simply use NSURLSession directly, with your own custom wrapper! In this post, I'll show you best-practices to do so. It'll probably take no longer than it would take to learn how to use Alamofire, and you'll be able to tweak it to your hearts content, to work around whatever quirks your backend team throws your way (we've all been there!).

Sample project

Before you get bored and give up on reading this post: if you'd like to see all this together, I've uploaded a sample project here: github.com/chrishulbert/Wattle.

It's deliberately not a cocoapod - I expect you to either read it as inspiration to write your own, or copy it in as a starting point and customise it to your needs. It's named Wattle in homage to Alamofire being named after a state flower - the wattle is the national flower of Australia.

Configuration

The first step in using NSURLSession is to create a configuration object. NSURLSessionConfiguration has three standard ones: Default, Ephemeral, and Background. These are class functions on the NSURLSessionConfiguration class.

Since it is always good practice to imitate Apple's frameworks in order to make things idiomatic, we'll add another class function for our own configuration. Simply create an extension on NSURLSessionConfiguration which creates a new configuration object based on Default, customise it a bit, and return it:

extension NSURLSessionConfiguration {
    /// Just like defaultSessionConfiguration, returns a
    /// newly created session configuration object, customised
    /// from the default to your requirements.
    class func mySessionConfiguration() -> NSURLSessionConfiguration {
        let config = defaultSessionConfiguration()
        // Eg we think 60s is too long a timeout time.
        config.timeoutIntervalForRequest = 20
        // Some headers that are common to all reqeuests.
        // Eg my backend needs to be explicitly asked for JSON.
        config.HTTPAdditionalHeaders = ["MyResponseType": "JSON"]
        // Eg we want to use pipelining.
        config.HTTPShouldUsePipelining = true
        return config
    }
}

Delegate

The next thing you'll need is a session delegate that implements NSURLSessionDelegate. I recommend calling it 'XYZURLSessionDelegate' where XYZ are your company initials. It won't need to be a singleton, as its instance is retained by the NSURLSession. It needs to inherit NSObject, although this may not be necessary in later Swift versions.

Here's an example of a delegate that allows self-signed certs for your dev/test servers, which I've almost always needed:

class MyURLSessionDelegate: NSObject, NSURLSessionDelegate {

    func URLSession(session: NSURLSession,
        didReceiveChallenge challenge: NSURLAuthenticationChallenge,
        completionHandler: (NSURLSessionAuthChallengeDisposition,
              NSURLCredential!) -> Void) {

        // For example, you may want to override this to accept
        // some self-signed certs here.
        if challenge.protectionSpace.authenticationMethod ==
                NSURLAuthenticationMethodServerTrust &&
                Constants.selfSignedHosts.contains(
                challenge.protectionSpace.host) {
            // Allow the self-signed cert.
            let credential = NSURLCredential(forTrust:
                challenge.protectionSpace.serverTrust)
            completionHandler(.UseCredential, credential)
        } else {
            // You *have* to call completionHandler, so call
            // it to do the default action.
            completionHandler(.PerformDefaultHandling, nil)
        }
    }

    struct Constants {
        // A list of hosts you allow self-signed certificates on.
        // You'd likely have your dev/test servers here.
        // Please don't put your production server here!
        static let selfSignedHosts: Set<String> =
            ["dev.example.com", "test.example.com"]
    }
}

URL session

NSURLSession already has a singleton session that you can use: sharedSession. Following Apple's example, let's make an extension on NSURLSession for our own session singleton. Swift won't let us use the 'static let' trick in an extension (maybe future versions will) so we need to use the nested struct trick. Finally, since the delegate is retained by the session according to Apple's docs, we can simply pass in a newly instantiated MyURLSessionDelegate:

extension NSURLSession {
    /// Just like sharedSession, returns a shared singleton
    /// session object.
    class var mySharedSession: NSURLSession {
        // The session is stored in a nested struct because
        // you can't do a 'static let' singleton in a
        // class extension.
        struct Instance {
            // The singleton URL session, configured
            // to use our custom config and delegate.
            static let session = NSURLSession(
                configuration: NSURLSessionConfiguration.
                    mySessionConfiguration(),
                // Delegate is retained by the session.
                delegate: MyURLSessionDelegate(),
                delegateQueue: NSOperationQueue.mainQueue())
        }
        return Instance.session
    }
}

URL requests

Next you'll need something to help you construct NSURLRequests. NSURLRequest already has two static helpers for this: requestWithURL and requestWithURL:cachePolicy:timeoutInterval:. But they don't hit the spot for what you'll probably need, so let's add another. Again, following Apple's example, I recommend adding it as a NSURLRequest extension. The following supports querystring and JSON-encoded body parameters, and per-request headers. You may want to modify it if, for example, your backend requires form or XML encoding:

extension NSURLRequest {
    /// Helper for making a URL request. This is to be used internally
    /// by the string extension, not by the rest of your app.
    /// It JSON encodes parameters if any are provided.
    /// Adds any headers specific to only this request too if
    /// provided. Any headers you use all the time should be in
    /// NSURLSessionConfiguration.wattleSessionConfiguration.
    /// You may want to extend this if your requests need any
    /// further customising, eg timeouts etc.
    class func requestWithURL(
        URL: NSURL,
        method: String,
        queryParameters: [String: String]?,
        bodyParameters: NSDictionary?,
        headers: [String: String]?) -> NSURLRequest {

        // If there's a querystring, append it to the URL.
        let actualURL: NSURL
        if let queryParameters = queryParameters {
            let components = NSURLComponents(URL: URL,
                resolvingAgainstBaseURL: true)!
            components.queryItems = map(queryParameters) {
                (key, value) in
                NSURLQueryItem(name: key, value: value)
            }
            actualURL = components.URL!
        } else {
            actualURL = URL
        }

        // Make the request for the given method.
        let request = NSMutableURLRequest(URL: actualURL)
        request.HTTPMethod = method

        // Add any body JSON params (for POSTs).
        if let bodyParameters = bodyParameters {
            request.setValue("application/json",
                forHTTPHeaderField: "Content-Type")
            request.HTTPBody =
                NSJSONSerialization.dataWithJSONObject(
                bodyParameters,
                options: nil, error: nil)
        }

        // Add any extra headers if given.
        if let headers = headers {
            for (field, value) in headers {
                request.addValue(value,
                    forHTTPHeaderField: field)
            }
        }

        return request
    }
}

Note that the helper above won't be directly used by other parts of your app, but is used by further helpers below.

Responses

I recommend using a Swift struct to manage your responses, as you can now add helper methods which come in extremely handy. It means you can add extra fields and helpers without needing any changes to your calling code, which is a big time saver in my experience.

/// This wraps up all the response from a URL request together.
struct WTLResponse {
    // Actual fields.
    let data: NSData!
    let response: NSURLResponse!
    var error: NSError?

    // Helpers.
    var HTTPResponse: NSHTTPURLResponse! {
        return response as? NSHTTPURLResponse
    }
    var responseJSON: AnyObject? {
        if let data = data {
            return NSJSONSerialization.JSONObjectWithData(
                data, options: nil, error: nil)
        } else {
            return nil
        }
    }
    var responseString: String? {
        if let data = data,
            string = NSString(data: data, encoding: NSUTF8StringEncoding) {
            return String(string)
        } else {
            return nil
        }
    }
}

String helper

And finally, here is the String extension that ties it all together and is used as the main entry point for the rest of your app. I'll concede that you may find it a bit too 'cute' to use a string extension for this, and so you may wish to use static methods on a class named 'MyNetworking' or such. Up to you. Also, you may want to add PUT and DELETE if your backend needs them. But here's what I think is nice:

extension String {

    typealias NetworkingCompletion = WTLResponse -> Void

    /// Simply does an HTTP GET/POST/PUT/DELETE using the receiver as the
    /// endpoint eg 'users'. This endpoint is appended to the baseURL which
    /// is specified in Constants below. These should be your main entry
    /// point into Wattle from the rest of your app.
    func get(parameters: [String: String]? = nil,
        completion: NetworkingCompletion) {
        requestWithMethod("GET",
            queryParameters: parameters,
            completion: completion)
    }
    /// Note that post's parameters are different, as they go in the body
    /// instead of the querystring.
    func post(parameters: NSDictionary? = nil,
        completion: NetworkingCompletion) {
        requestWithMethod("POST", 
            bodyParameters: parameters,
             completion: completion)
    }

    /// Used to contain the common code for GET and POST and DELETE and PUT.
    private func requestWithMethod(method: String,
        queryParameters: [String: String]? = nil,
        bodyParameters: NSDictionary? = nil,
        completion: NetworkingCompletion) {

        // Create the request, with the JSON payload or querystring if necessary.
        let request = NSURLRequest.requestWithURL(
            NSURL(string: self, relativeToURL: Constants.baseURL)!,
            method: method,
            queryParameters: queryParameters,
            bodyParameters: bodyParameters,
            headers: nil)
        let task = NSURLSession.sharedWattleSession.dataTaskWithRequest(request) {
            data, response, sessionError in

            // Check for a non-200 response, as NSURLSession doesn't consider
            // that as an error.
            var error = sessionError
            if let httpResponse = response as? NSHTTPURLResponse {
                if httpResponse.statusCode < 200 || httpResponse.statusCode >= 300 {
                    let description = "HTTP response: \(httpResponse.statusCode)"
                    error = NSError(domain: "Custom", 
                        code: 0, 
                        userInfo: [NSLocalizedDescriptionKey: description])
                }
            }

            // Wrap up the response.
            let wrappedResponse = WTLResponse(
                data: data, 
                response: response,
                error: error)
            completion(wrappedResponse)
        }
        task.resume()
    }

    // MARK: - Constants

    struct Constants {
        /// This is the base URL for your requests. You'll of course want
        /// to make this point at your servers.
        static let baseURL = NSURL(string: "https://api.github.com/")!
    }
}

Using it

So, now it's all in place, how do you use this from the rest of your app? Quite simply:

// Simplest possible example.
"emojis".get { response in
    println(response.responseJSON)
}

// Some parsing (I recommend you should put parsing as
// an extension on your model classes).
"users".get { response in
    if let users = response.responseJSON as? [NSDictionary] {
        let names = users.map { $0["login"]! }
        println(names)
    } else {
        println("Error: \(response.error)")
    }
}

// A querystring param.
"meta".get(parameters: ["since": "2015-01-02"]) { response in
    println(response.responseJSON)
}

Hope someone finds this helpful :)


You can see older posts in the right panel, under 'archive'.

Archive

Swift KVO alternative 23 Jul 2015

Swift Keychain wrapper 21 Jun 2015

Swift NSURLSession wrapper 12 Jun 2015

iOS8 View Controller transitioning bug 17 Apr 2015

IB Designable 18 Mar 2015

iOS App Architecture 2 Mar 2015

Video Course Launch 14 Feb 2015

Video Course Pre-launch 8 Feb 2015

Blogging Platforms 13 Jan 2015

Mobile in 2014 - Year in Review 11 Jan 2015

Secret Keys talk 16 Nov 2014

Dimmi 11 Nov 2014

Project setup in Xcode6 22 Oct 2014

Uploading to an S3 bucket from iOS 15 Oct 2014

iOS8 App Testing Roundup 28 Sep 2014

Storing obfuscated secret keys in your iOS app 16 Sep 2014

Getting Core Location / CLLocationManager to work on iOS8 14 Sep 2014

Accessing the response body in failure blocks with AFNetworking 2 10 Sep 2014

How to allow your UITextFields to scroll out of the way of the keyboard 8 Sep 2014

How to subclass UIButton in iOS7 and make a UIButtonTypeSystem 4 Sep 2014

New season 1 Aug 2014

House finished 17 Jun 2014

WebP decoding on iOS 9 Feb 2014

Moving on again 22 Jan 2014

Lossy images for retina iPads - JPEG vs WebP 30 Nov 2013

Career options I wish I knew about when I was younger 20 Oct 2013

Positivity and your friends 7 Oct 2013

Tactility 26 Jul 2013

WWDC-induced narcolepsy 15 Jul 2013

Back on rails 31 May 2013

Full circle 6 May 2013

Programmatic UI on iOS 3 May 2013

Screencasts and positivity 8 Apr 2013

Year of positivity 14 Mar 2013

iOS Dev State of the Union 6 Feb 2013

Adventures with IAPs 3 Feb 2013

No longer a Googler 23 Dec 2012

Localising iPhone apps with Microsoft Translator 8 Dec 2012

Fight back (app biz update 13) 12 Nov 2012

Sent to the backburner (app biz update 12) 25 Oct 2012

Lisi Schappi 7 Oct 2012

Today's happy plateau (app biz update 11) 26 Aug 2012

First week's sales of Today (app biz update 10) 19 Aug 2012

Today launch! And a difficult decision made... (app biz update 9) 15 Aug 2012

Approved! (app biz update 8) 5 Aug 2012

Creating a graph in Objective-C on the iPhone 3 Aug 2012

Hurry up and wait (app biz update 7) 30 Jul 2012

Today app marketing site 27 Jul 2012

Today app submitted 25 Jul 2012

UIAlertView input wrapper 24 Jul 2012

Mentoring 23 Jul 2012

This is too hard! (app biz update 6) 20 Jul 2012

Perspectives (app biz update 5) 9 Jul 2012

4th starting-my-own-biz update 1 Jul 2012

ScrumFox landing page 28 Jun 2012

Server Scope landing page 27 Jun 2012

Telstra Calls and Data Usage 26 Jun 2012

Service History + Dropbox 26 Jun 2012

Impromptu Presenter 26 Jun 2012

Fertility Tracker 26 Jun 2012

Baby Allergy Tracker 26 Jun 2012

Starting my own business, update 3 22 Jun 2012

Starting my own business, update 2 17 Jun 2012

Starting my own business - First update 10 Jun 2012

I must be crazy 6 Jun 2012

Finding your location on an iPhone 7 May 2012

A generous career 4 May 2012

Skeleton Key Cocoaheads presentation 3 May 2012

CHBgDropboxSync - Dropbox auto-sync for your iOS apps 1 May 2012

That book about that Steve Jobs guy 30 Apr 2012

Another app marketing idea 23 Apr 2012

Sweet grouped tables on the iPhone 17 Apr 2012

Skeleton Key App 11 Apr 2012

Another app marketing idea... 5 Apr 2012

Quickly check for any missing retina graphics in your project 3 Apr 2012

Skeleton Key Password Manager with Dropbox 2 Apr 2012

RC Boat motor finally mounted 2 Apr 2012

Promoting apps presentation slides 1 Apr 2012

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

The Finishing Line 20 Mar 2012

Using Launchd to run a script every 5 mins on a Mac 20 Feb 2012

Generating AES256 keys from a password/passphrase in ObjC 20 Feb 2012

Indie iPhone app marketing, part 2 19 Feb 2012

My App Manifesto: Syncing + Dropbox + YAML = Awesome 15 Feb 2012

Indie iPhone App Marketing part 1 7 Feb 2012

Perspectives 2 Feb 2012

Accountability and Free Will 1 Feb 2012

Badassery 31 Jan 2012

Sacrifice 30 Jan 2012

Lead Yourself First 29 Jan 2012

How to ping a server in Objective-C / iPhone 26 Jan 2012

iOS Automated Builds with Xcode4 16 Jan 2012

Xcode 4 - Command line builds of iPhone apps 15 Jan 2012

Guest post by Jason McDougall 13 Jan 2012

Scouts, Games and Motivation 10 Jan 2012

2011 Re-cap 8 Jan 2012

Ruby script to increment a build number 4 Jan 2012

Turning 30? All ideas, no execution? 18 Dec 2011

CHDropboxSync - simply sync your iOS app's documents to Dropbox 14 Dec 2011

Deep-enumerating a directory on the iphone, getting file attributes as you go 10 Dec 2011

Getting a date without the time component in objective-c 6 Dec 2011

Memory management in Objective-C 4 Dec 2011

Starting small 29 Nov 2011

Dictionary Types Helper 29 Nov 2011

Observer Pattern in Objective-C 16 Nov 2011

Why you should give presentations 13 Nov 2011

How to get a programming or design job in Sydney 9 Nov 2011

Custom nav bar / toolbar backgrounds in iOS5 8 Nov 2011

Stuck 27 Oct 2011

Dead easy singletons in Obj-C 19 Oct 2011

JSON vs OCON (Objective-C Object Notation) 18 Oct 2011

In defence of Objective-C 16 Oct 2011

Update the MessagePack objective-c library to support packing 12 Oct 2011

Icons 11 Oct 2011

How to host a site on Amazon AWS S3, step-by-step 7 Oct 2011

Drawing a textured pattern over the default UINavigationBar 6 Oct 2011

Markdown Presentations 1 Oct 2011

More MegaComet testing: Ruling out keepalives 15 Sep 2011

MegaComet test #4 - This time with more kernel 14 Sep 2011

Building People 10 Sep 2011

Half way there: Getting MegaComet to 523,000 concurrent HTTP connections 5 Sep 2011

Making a progress bar in your iPhone UINavigationBar 22 Aug 2011

Hacker News Reader 20 Aug 2011

How to programmatically resize elements for landscape vs portrait in your iphone interface 16 Aug 2011

MegaComet testing part 2 3 Aug 2011

Australian Baby Colours 28 Jul 2011

Boat prop shaft 25 Jul 2011

Megacomet with 1 million queued messages 24 Jul 2011

Installed the strut and rudder 18 Jul 2011

Painted the inside of the boat 17 Jul 2011

Fuzzy iphone graphics when using an UIImageView set to UIViewContentModeCenter 13 Jul 2011

My 3 Data and Calls Usage 11 Jul 2011

Reading a line from the console in node.js 10 Jul 2011

Trim whitespaces on all text fields in a view controller 9 Jul 2011

Final finish 9 Jul 2011

MessagePack parser for Objective-C / iPhone 30 Jun 2011

Lacquering the starboard side 25 Jun 2011

What do do with EXC_ARM_DA_ALIGN on an iPhone app 23 Jun 2011

Lacquering the hull 23 Jun 2011

Staining the boat 22 Jun 2011

NSMutableSet with weak references in objective-c 20 Jun 2011

Iphone gesture recogniser that works for baby games 20 Jun 2011

Image manipulation pixel by pixel in objective C for the iphone 19 Jun 2011

Baby Allergy Tracker 12 Jun 2011

Power sanding the deck 10 Jun 2011

Planing the edge of the deck 2 Jun 2011

Figured out the deck 2 Jun 2011

Boat bulkheads 2 Jun 2011

Simulating iOS memory warnings 31 May 2011

Putting a UIButton in a UIToolbar 29 May 2011

How to allow closing a UIActionSheet by tapping outside it 29 May 2011

Finding the currently visible view in a UITabBarController 24 May 2011

Random Chef 17 May 2011

Centered UIButton in a navigation bar on the iphone 16 May 2011

Little Orchard 13 May 2011

Boat update 13 May 2011

How to get the current time in all time zones for the iphone / obj-c 12 May 2011

Design portfolio 10 May 2011

Tricks with grand central dispatch, such as objective-c's equivalent to setTimeout 9 May 2011

How to make an iphone view controller detect left or right swipes 5 May 2011

Centered section headers on a UITableView 5 May 2011

Christmas in may 4 May 2011

Finished trimming the boat (its floatable now!) and got some parts 29 Apr 2011

How to make a multiline label with dynamic text on the iphone and get the correct height 27 Apr 2011

Forcing an image size on the image in a table view cell on an iphone 20 Apr 2011

Git on the Mac 19 Apr 2011

Build a url query string in obj-c from a dictionary of params like jquery does 12 Apr 2011

Rendering a radial gradient on the iphone / objective-c 11 Apr 2011

Skinning the port side of the boat 8 Apr 2011

Skinning the side of the boat 5 Apr 2011

Sending a UDP broadcast packet in C / Objective-C 5 Apr 2011

How to talk to a unix socket / named pipe with python 4 Apr 2011

Skinning the bottom of the boat 31 Mar 2011

Service discovery using node.js and ssdp / universal plug n play 30 Mar 2011

Extremely simple python threading 29 Mar 2011

New rescue boat 26 Mar 2011

HttpContext vs HttpContextBase vs HttpContextWrapper 5 Nov 2010

Simple C# Wiki engine 30 Sep 2010

Simple way to throttle parts of your Asp.Net web app 29 Sep 2010

How to implement DES and Triple DES from scratch 4 Aug 2010

How to use sessions with Struts 2 30 Jul 2010

How to use Cookies in Struts 2 with ServletRequest and ServletResponse 30 Jul 2010

Using Quartz Scheduler in a Java web app (servlet) 27 Jul 2010

Javascript date picker that Doesn't Suck!(tm) 27 Jul 2010

Using Oracle XE with Hibernate 20 Jul 2010

A simple implementation of AES in Ruby from scratch 29 Jun 2010

Asp.Net Forms authentication to your own database 28 May 2010

AS2805 (like ISO8583) financial message parser in C# 7 May 2010

Ruby hex dumper 4 May 2010

Using Spring to manage Hibernate sessions in Struts2 (and other web frameworks) 13 Jan 2010

Emails in C#: Delivery and Read receipts / Attachments 12 Jan 2010

Using Java libraries in a C# app with IKVM 16 Dec 2009

Learning Java tutorial 27 Nov 2009

Using generic database providers with C# 17 Nov 2009

Scheduled task executable batch babysitter 29 Oct 2009

Working with query strings in Javascript using Prototype 30 Sep 2009

Still fighting with String.Format? 9 Sep 2009

How I'd build the next Google 24 Aug 2009

Getting IIS and Tomcat to play nicely with isapi_redirect 24 Aug 2009

Using the new ODP.Net to access Oracle from C# with simple deployment 11 Aug 2009

C# Cryptography - Encrypting a bunch of bytes 14 Jul 2009

Sorting enormous files using a C# external merge sort 10 Jul 2009

Reconciling/comparing huge data sets with C# 9 Jul 2009

Some keyboard-friendly DHTML tricks 10 Jun 2009

How to figure out what/who is connected to your SQL server 18 Mar 2009

Adding a column to a massive Sql server table 16 Mar 2009

Multithreading using Delegates in C# 10 Mar 2009

Using C# locks and threads to rip through a to-do list 6 Feb 2009

Using threads and lock in C# 3 Feb 2009

Setting a form name and onsubmit using form_for in rails 2 14 Jan 2009

Compressing using the 7Zip LZMA algorithm in C# beats GZipStream 14 Jan 2009

Bare minimum HTML that validates 22 Dec 2008

MS Sql Server 2005 locking 17 Dec 2008

Simple Comet demo for Ruby on Rails 19 Nov 2008

Geocoding part 2 - Plotting postcodes onto a map of Australia with C# 24 Oct 2008

Using evolutionary algorithms to make a walkthrough for the light-bot game with C# 20 Oct 2008

How to tell when memory leaks are about to kill your Asp.Net application 16 Oct 2008

C# version of isxdigit - is a character a hex digit? 15 Sep 2008

Geocoding part 1 - Getting the longitude and latitude of all australian postcodes from google maps 26 Aug 2008

Converting HSV to RGB colour using C# 14 Aug 2008

Opening a TCP connection in C# with a custom timeout 11 Aug 2008

Oracle Explorer - a very simple C# open source Toad alternative 31 Jul 2008

Linking DigitalMars' D with a C library (Mongrel's HTTP parser) 23 Jun 2008

Connecting to Oracle from C# / Winforms / Asp.net without tnsnames.ora 16 Jun 2008

A simple server: DigitalMars' D + Libev 6 Jun 2008

Travelling from Rails 1 to Rails 2 9 Apr 2008

Rocketsale 9 Apr 2008

Online Rostering System 9 Apr 2008

DanceInforma 9 Apr 2008

Client Analyser 9 Apr 2008

How good is this??? 16 Dec 2007

Using RSS or Atom to keep an eye on your company's heartbeat 10 Nov 2007

Easy Integrated Active Directory Security in ASP.Net 24 Oct 2007

First post 17 Oct 2007