A C# developer learns Swift Part 3: API Callbacks
Previously, I mentioned that a major hurdle to learning Swift was the state of the API. Primarily that it is still Objective C based. Often your code will need to respond to external events generated by these libraries. Unlike C#, neither Objective C or Swift have the equivalent to the “event” construct. The Objective C libraries rely on three different ways to handle callbacks: selectors, delegates, and closures.
Selectors are a language feature in Objective C where you specify a reference to an object and the name of a method to call on that instance.
In my example, I’m programmatically hooking up to the click event on a couple of buttons. I’m setting the target to the current instance that viewDidLoad is implemented in, and setting the action to be either either the Save() or Cancel() methods implemented in the same object.
This feature requires an Objective C visible Swift type. So you need to mark your object type with the @objc attribute or inherit a type from an Objective C library.
Not to be confused with C# delegates, which are more akin to Swift’s closures. Where Selectors map a single cause and effect relationship, a delegate represents a more complicated coupling of interactions. In Swift, this takes the form of a reference to an object that implements a specific protocol.
Swift protocols have two quirks that make them a little different from C# interfaces. For one, you can declare static methods and fields on your interface, something that C# expressly forbids. Secondly, and more importantly for this discussion, you can load up your protocol with optional methods and fields. So yeah, you can declare your class is implementing a protocol, and then not have to implement any of its contracts.
Like with Selectors, to declare optional items in your protocol, it has to be objective C visible. If you have a reference to a protocol with optionals, you can use the optional chaining operator to call them safely. The method call will just return nil in the case where the optional requirement wasn’t implemented.
Ok, so how does this relate to using the Objective C APIs you ask? Well, when rigging together your UI, you’ll want to interact with the various controls you present to the user. Your view controller class will need to implement various protocols to do so. For instance, to handle the events generated by a UIImagePickerControl you need that controller to also implement the UIImagePickerControllerDelegate protocol.
Implementing any of the optional methods from the protocol will allow you to handle that particular callback from the image picker. In this example I implemented the optional method that allows me to handle the user accepting a image they just took with the camera.
Closures represent anonymous blocks of code that can be passed around. They’re called Blocks in Objective C, and are analogous to C#’s delegates. The AssetsLibrary framework for accessing your photos and documents seems to favor this approach.
Here we declare a closure for handling the iteration through all the asset groups plus one for the error case. Within the group closure, we also have to create another closure to iterate each asset in the group. The syntax is pretty similar to declaring a generic Action or Func in C#.
(Don’t get me started on needing the unsafe pointers to quit the loop–I’m still looking for a better way to handle that.)