Swift Pitfalls

I’ve started a couple experiments in iOS 8 development using Apple’s new language Swift and learned a few lessons that I want to share.

Blocks and Automatic Reference Counting (ARC)

Swift supports blocks, or “closures”, as other languages call them. You can provide a block as handler, e.g. for an asynchronous HTTP request. This is excellent if you want to do updates in the background and a simple way to handle some updates (data and UI) when the new data has arrived.

A block in Swift will capture references that are used form the surrounding context. If you use self reference in the block, a reference to it will be retained.

You can work around this by defining the captured references as weak references, specifically one of the following types:

Captured references can be defined in a block like this:

var block = {
    [unowned self, weak otherReference] // captured references
    (parameter) in // input parameters to the block
    self.name = parameter 
}

The block will then respectively not keep a strong reference to the captured objects and allow ARC to clean up object accordingly when needed.

I have a bit of code that can issue a simple JSON-RPC request dynamically, and it was retaining references to self before I added the [unowned self] bit.

private func asyncRequest(command: String, parameters: [String], callback: ((NSData!, NSURLResponse!, NSError!) -> Void)) -> 
NSURLSessionDataTask {
    let url = NSURL(string: command, relativeToURL: baseUrl)
    var request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"
    request.HTTPBody = "{\"nocache\":\(NSDate().timeIntervalSince1970),\"method\":\"\(command)\",\"params\": [\(parameters)]}".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
    
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request, callback)
    return task
}
	
// somewhere else in the code...

var task = self.asyncRequest("rpcmethod", parameters: ["1234"]) {
    [unowned self] (data, response, error) in
    self.groupCache = parse(data)
}

UITableView Updates from Dynamic Data Sources

And another interesting thing, related to UIKit, not so much to Swift about updating UITableViews that show data from external services (e.g. via REST). This article on codeproject.com discusses a solution for Updating UITableView with dynamic data sources.

Also the apple developer documentation on Batch Update of UITableView Operations is very interesting.