Posts tagged objective-c
Swift Development with Cocoa

Our new book is finally out, in early release unedited ebook form! Today Swift Development with Cocoa was released by O'Reilly Media.

We're really proud of this book (which we wrote with our friend and frequent collaborator Tim Nugent), and now's a great time to grab it – O'Reilly is running a 50% off promotion on all the great new iOS 8-related books until 5AM PDT on 25 September 24!

The code samples for Swift Development with Cocoa are available on GitHub too, if you'd like to play with some Swift.

While you're at it, check out our friend Tony Gray's new book, Swift Pocket Reference – Secret Lab wouldn't exist without his encouragement and support, and he's written a damn fine pocket reference for Swift!

Stay tuned for more books, as well as the final release of these Swift books. Let us know if you have any comments on the early release editions! 


Thoughts on WWDC14

Some quick thoughts from Secret Lab on the mind-blowing collection of WWDC 2014 announcements from Apple.

OS X Yosemite

Pretty! Made simpler. Not super sold on translucency, though.

Handoffs and Continuity is awesome. Will be super useful. Devs get access to this too. Reminds us of the excellent “Send to Chrome” feature in Android. Only really polished.

iOS 8

Not a huge amount of new stuff, visuals wise; however, there are some awesome behind the scenes changes.

Custom Actions, Photo Editing, Sharing Options can all be provided by apps. You can make your app provide services to other apps. This is AWESOME - it’s going to make the app ecosystem quite a bit richer.

Android’s had this for some time, and it’s great to see it in iOS.

The ability to put widgets in the notification center is also great, lots of devs are going to make some great stuff with this.

Being able to share documents between apps without having to copy them is going to be Super Nifty. This has been a real weakness of iOS until now.

Swift

WOW. Apple developed an entire language, wrote all the docs, and wrote all the supporting tools for it, without it leaking. This is really impressive.Can’t wait to use this.

The language is very modern. Its syntax feels like a mashup of Python, Haskell and Ruby.

Interoperation with Obj-C is rather nicely handled. They’ve directly translated ObjC’s arguments-are-embedded-into-method names approach into named parameters. The goal was clearly to make it as painless as possible to work with both languages in a single project.

Something that’s interesting is it’s completely opposed to Objective-C’s way of doing things is that, while ObjC allows sending messages to nil (thereby making it safe to not have to do null checks), Swift instead guarantees that all values that are not Optionals are non-null. Optionals are a very cool feature: in other languages, the concept of “nothing” is usually represented by a special value (for example, Lua’s ‘nil’ value), or by convention (for example, in C, the value 0 means ‘nothing’). This creates its own problems; if you use a special value, comparing it to other objects means you have to do type conversions, and if you instead use the convention of zero meaning null, you have to do checks. Objective-C goes some of the way towards helping with this: it defines ‘nil’ as a special value that’s represented a zero pointer, but calling methods on it is safe because the runtime automatically returns if it notices you’re trying to call methods on nil.

This is nicer than crashing, but it can lead to problems, since if an object you’re trying to work with is unexpectedly nil, you’ll get bugs. Not crashing bugs, but weird behaviour bugs.

The Optionals system is nicer. In Swift, a value is either guaranteed to be a valid one, or else is explicitly known to sometimes be nil.

For example: if you’re converting strings to integers, your code looks like this:

let theString = "123"

let theInt = theString.toInt()

In most languages, the ‘toInt()’ method would return a value that represents ‘not valid’, such as 0. But in Swift, it returns an optional int - that is, a value that MIGHT represent nothing, but if it doesn’t represent nothing, then it’s GUARANTEED to be an integer and nothing else.

This makes things quite a bit safer, since the compiler’s able to do more checking, and is able to reason about your code better.

Swift is filled with this kind of thing. Another example: in C and similar langauges, the assignment operator (=) returns a value, like this:

a = b = 3 // sets both a and b to 3

In Swift, that doesn’t apply. This means that the following is actually a compiler error (it’s just a warning in ObjC):

if x = y {



}

We’re not huge fans of the range operators: a...b means “range from a to b, including b” and a..b means “range from a to b, not including b”. Notice that they only differ by a single period. That’s going to lead to bugs, due to typos.

The mutability of variables depends on whether or not the variable is declared as a constant or not. This is nicer than Objective-C, which has two different classes for each type based on whether it’s mutable or not (ie NSString vs NSMutableString)

This only applies to strings, arrays, dictionaries, and other low-level things. We’re still going to be stuck with NSURL vs NSMutableURL for a while.

Playground is super cool. Reminds us of IPython, in that you can figure out your code without it having to be run inside a larger app. This is going to make development a lot faster.

App Store

Being able to show videos and make app bundles (with discount) is going to be neat. Not a huge game changer for us, but any increase in app store functionality is good.


Using JSON to load Objective-C objects

You want to write an iOS or OS X app that quickly and easily retrieves some data from a server and converts it to an Objective-C class. Also, you want to write the server using something standard, like Django or Ruby on Rails.

The standard way that you’d do this would be using NSCoder, where your client application would receive the data and you’d unpack it like so:

However, the file format for serialised objects is internal to iOS and OS X, and is also a binary format that’s very difficult to read while in transit.

We recently had a similar problem, where we wanted to have our server send data in JSON format, which we like because JSON’s pretty human-readable. We could implement our own custom implementation of NSCoder, but we were after a more lightweight solution.

Key-value coding

This is where key-value coding comes in. Key-value coding is a feature of Cocoa that lets you access properties and instance variables of class at runtime by name, rather than simply at compile time.

For example, if you had a class that had an NSString property called “name”, you could access it like this:

Or you could access it with key-value coding, like this:

Likewise, you can set the name property like this:

But you could also set it using key-value coding, like this:

The advantage of key-value coding is that you can generate the keys at run-time. Your code doesn’t have to know about the properties and variables kept inside an object in order to attempt to get and set the values.

This is where our lightweight serialisation comes in. Let’s say that we’ve received some JSON data that looks like this:

In this example, we’ve also got an Objective-C object that has matching properties:

Converting the JSON data into a dictionary is pretty easy.

You can then create the Objective-C class from this dictionary by creating a new Employee object, and then iterating over each of the keys in the dictionary, using setValue:forKey: to set the values.

This works even for non-object properties like Employee’s income property, which is an int. In this case, the dictionary loaded from the JSON contains an NSNumber object for the income field; when setValue:forKey: is used for that key, it automatically extracts the int from the NSNumber and applies it to the class.

There’s an even easier way to set all of the values:

Loading objects when you don’t know the class

Another possible use case is one where you receive a chunk of JSON, but you don’t know ahead of time what kind of object the JSON should be turned into. This is where NSClassFromString comes in handy.

If your JSON object contains a field called, say, class, you can use that to create the empty object. Like so:

The reason we use NSObject in the above example is because all NSObjects support the key-value coding methods. Even though loadedObject is treated as a generic NSObject, the fact that it was created with whatever class ObjectClass is determined to be means that the object will be what you specify.

Dangers and Caveats

This technique only applies for simple properties, like strings and numbers. More complex data types or references to other Objective-C objects need to be handled differently.

If you use setValue:forKey: on a key that doesn’t exist in the target object, the object will throw an exception and crash. There are a couple of ways you can handle this; one is to implement the setValue:forUndefinedKey: method in your classes.

This method is called when you try to set a value for a property or instance variable that doesn’t exist. The default implementation throws an exception and crashes; you can implement your own that leaves a warning, for example.

A final note: this is a very quick-and-dirty solution. If you want more reliable behaviour, you’ll need to add more checks and validation code. For simply loading objects, it works pretty well.


Using OmniGraffle as a level editor

This was a fun one. As we've mentioned before, we're currently working on a board game for a client. Without going into the details, the game is based on nodes on a game board that are linked together; players move between connected nodes, and claim territory.

When coding up the game, we initially generated the game boards in memory, by directly instantiating 'node' and 'link' objects. Then, when it came time to make the game load different boards on demand, we created a JSON-based data structure that defines the nodes and links. It looks a little something like this:

This structure defines two nodes, including their names and positions, as well as a relationship that links the two together. (Because the graph is nondirectional, we didn't want to define links in the node data structure itself.)

This is all well and good for simple game boards, like this:

tutorial-board

But then the client said, "cool, can you make this?"

hex-board

And we were all:

Reaction_ItalianSpiderman

Clearly, hand-coding wasn't an option, and a tool was needed. Writing one ourselves wouldn't have been the best use of our time, so we looked at our favourite Mac app ever: OmniGraffle Pro. OmniGraffle already knows about objects and connections, and it exposes all of this information through AppleScript.

So, we went searching, found this excellent Gist by Michael Bianco, and adapted it into one that extracts the information we need and generates the game board data that we care about.

Loosely put, it turns this:

omnigraffle-board

Into a level that can be loaded:

sembl-board

How it works

First, we designed the level. In this board game, there are only nodes and connections; we represented nodes as circles, and connected the nodes with lines.

omnigraffle-shot

The first thing the script does, we get access to OmniGraffle via the Scripting Bridge:

OmniGraffle exposes a list of shapes, which AppleScript can query for important information such as the origin point, and its text. You can also query and set a special "tag" property for each shape, which is useful for storing an identifier. We base the identifier on the text of the shape, if it has any; otherwise, we use a random number.

So, to generate the list of game nodes, we ask OmniGraffle for all shapes, and format the result into a hash, which we store in an array for later.

When generating the hash for a node, we can also make use of the user data dictionary that OmniGraffle Pro exposes. This lets you set custom key-value pairs for a shape, which is very useful for setting things like which player owns a node, or at what point in the game the node becomes active. This is a simple matter of merging in the userData hash.

Once all nodes have been processed, we know that all shapes have had a tag associated with them; we can then iterate over all shapes a second time, this time generating information for each connection.

Finally, we export the nodes and links as JSON:

Because this script operates on the frontmost open document in OmniGraffle and outputs to stdout, saving the JSON is as simple as a one-line command: $ ruby graffle2board.rb > MyAwesomeBoard.board

Summary

This is a pretty powerful technique, since it lets us design the game maps with a powerful (and, more importantly, pre-existing) tool and import them exactly the way we want them. We're definitely going to be using this more in the future.

You can see the script in GitHub!


UIView+Glow: Fancy Glowing Effects for Everyone

We recently needed to add a tutorial to a board game (see SLTutorialController), and realised that we needed a way to highlight various controls and other user interface elements that the user should interact with next. A common way that this is handled is by making things glow, often with an animation. So, we wrote UIView+Glow. It's a very simple category that adds two methods: startGlowing and stopGlowing. When you call startGlowing, the view will start to pulse with a soft light; this effect is removed when stopGlowing is called.

You can see a video of it in action here:

It's available on our GitHub now!