Wednesday, September 30

Is it worth while transitioning from Objective C to Swift?

I 'm late to this bandwagon. However I had a heavy investment in an Objective C code base and a lot of distractions. Enough with the excuses, better late than never.

I know others have held off for many of the same reasons I did. So the question is useful. Was transitioning to swift worth it? The answer is a definite yes.

The Pros

No pointers and no nil-able values or objects unless they are wrapped in an option. This cuts down on a large class of errors.

Named parameters. This language is targeted for Objective C programmers so of course it has name parameters, however I still count it as a plus because named parameters increase readability and are a good idea, even C# has named parameters theses days.

No lisp-like nested square brackets everywhere (yes I know lisp uses round brackets, however I am talking about the nesting behaviour)

Immutable values using the let keyword. This reminds me of Scala's val and var keywords and of F#'s let keyword, although F# makes it harder to make values and objects mutable. Immutable values can make an application easier to reason about and make it easier to do concurrent programming (less need for locking)

No more header files.

Memory management that doesn't feel like a tacked on after thought .

Only one form of closure instead of the two different flavours in Objective C (selectors and blocks)

The 'if let' statements ability to chain together multiple let statements capped with a where cause reduces nesting and as nesting plays havoc with readability this is all to the good. There is a 'if var' version but I never see it used.

Swift has its own REPL which in Swift's case is called a playground. REPLs are common in many interpreted languages, they are ideal for learning and experimentation. REPL is pronounced 'reppel' and stands for Read Evaluate Print Loop and at its heart in a very simple, effective and old piece of technology.

No more need to box and unbox value types just to use collections. I remember when C# had this problem (versions 1.0 and 1.1 fixed in 2.0), but at least C# 1.1 had the __box and __unbox keywords,  in Objective-C you have to wrap and unwrap value types by hand.

Swift has generics, type safety and even type inference. Plugging that hole (lack of generics) in the type system pays off massive benefits in reduction of errors and increased ease of use. There is no way to have general purposes containers like lists and dictionaries without either having a generic type system, using dynamic types or breaking the type system by casting away type.

Less use of special characters in syntax, no more semi-colons at the end of your lines and a more modern cleaner looking syntax.

Initial Annoyances / Gotchas

You will need to lose the habit of surrounding if conditions with brackets as this can break things. This is initially is frustrating, but when you get used to it, it actually looks cleaner.

Significant white space between operators and operands or lack there of will turn binary operators into prefix unary operators.

Xcode habit of warning you that you have not used a declared variable or constant straight after you have declared it and before you have had the chance to type the line that will use it, can initially be distracting.

The Cons

I am used to uninformative and obscure error messages, but Xcode has reached a new low in this lost art of sowing confusion. After a while you get an idea about what it could be complaining about, but even when you know what is causing the problem, drawing a meaningful relationship between the error message and the cause of the problem can be bewildering.

The navigation and intellisense  tends to break when you need them most.

No refactoring support for swift yet compared to Xcode refactoring support for its other supported languages, not that Xcode Objective-C refactoring support is terribly good, but at least its there.

Lost Opportunities

There is a lot I could say about this, but Objective-C does worse in features I want to complain about so I will just point you to a post that Rob Napier wrote about how swift is not functional and save the rant I was going to write here for another blog post.

The Experience

The first one or two weeks was frustrating. Most of the frustration was centred around the compiler. However the learning curve was surprisingly easy. After two weeks I felt more comfortable with Swift than Objective-C even though I have been using Objective-C for years. Their is very little in Swift that isn't a standard expected feature in a modern programming language. Even the syntax and the keywords are pretty stock standard. Given the blandness of Swift the main reason for its existence is obviously to have built-in compatibility with the existing libraries and APIs and to make migration from Objective-C and interoperability with Objective-C easy. In achieving these goals Swift is successful.

Conclusion

I am not going to rewrite all my Objective-C code base in Swift. However all new work is going to be in Swift and even major modifications to old projects will probably be in Swift as you can mix the two languages in the same project.




Tuesday, September 29

The Secret to Managing Images, Sounds and other Resources for Mobile Apps


Four simple rules
  1. Automate, Automate, Automate
  2. Keep all the source artefacts and scripts needed to produce the final resources under source control e.g git or mercurial (don't bother with the derived images)
  3. Give everything long descriptive names and a systematic logical folder hierarchy.
  4. Use texture atlases rather than individual images ( originally I used Zwoptex to generate texture atlases for me, but now days Xcode does it automatically for me ).


When you first start adding images and sounds to your app it doesn't seem like a big deal to do things manually. Any half baked semi-functional  process or algorithm works as long as 'n' is small. But as the number of images and sound clips grow you will pay a higher and higher price for poor decisions you made at the start. It does not take long before you have hundreds of images and sounds. Any technique that allows you to cut down the number of images is a technique you should use. A favourite trick of of mine is to split an image into several layers and to tint one or more layers programatically to get several different colour themed images.

One of the reasons images breed like rabbits is the different resolutions and aspect ratios of different devices. Making different images for each device manually is the road to insanity. There are two different approaches to get around this problem and I use them both.

Solution 1



Make your images at the highest resolution and then down sample to get your lower resolution. One of my favourite tools to do this is ImageMagick as it has a command line interface and therefore can be called from a script. You can use it to resize, crop and rotate images plus much, much more. If I am using a Mac prefer to use the MacPorts package manager to install apps like this, if I am using Windows I use the Chocolatey package manager.

Once you have a package manager  you type in the following into the terminal for the mac
sudo port install ImageMagick
or the following into the command window for Windows
choco install imagemagick.app
Nicholas Waynik has a tutorial on how to use the resulting images on the iPhone and iPad.

Solution 2


Use a vector format like SVG and then you can rasterise it to any resolution you want. I tend to use this solution as I have the habit of going back and spitting my old images into parts in order to animate or reuse the image in someway. It is easier to modify a vector image later if you have to. Inkscape is a good drawing app to use for creating the images.

It does have a command line interface but you have make it jumps though hoops if you want to make it rasterize an entire folder of vector images. Which is exactly what I am always going to ask it to do. You do not want to create the final rasterized (e.g. *.png) images this manually though the GUI. Remember rule number 1. I use the following snippet in the bash scripts I use to generate the final images.

for i in /full-directory-path/*.svg; do /Applications/Inkscape.app/Contents/Resources/bin/inkscape $i -w 100 -h  200 --export-png=`echo $i | sed -e 's/svg$/png/'`; done

and for the 2x images

for i in /full-directory-path/*.svg; do /Applications/Inkscape.app/Contents/Resources/bin/inkscape $i -w 200 -h  400 --export-png=`echo $i | sed -e 's/.svg$/@2x.png/'`; done

You can either copy and paste these command into a mac terminal window or place them in a text file with a *.command extension to create a clickable command.

I modified the this script based on a piece of bash script voodoo I got from gastarbeiten who in turn got it from someone called forger. The original script no longer works because the upgrade to inkscape 0.91 broke it, thankfully it only took a minor tweak to get it working again. Fair warning these scripts sometimes need little care and feeding every now and again. I seem to need to fix them about once every 6 months. Despite the very occasional annoyance these scripts are a life saver.

Originally I used batik to do the rasterization as it supports processing multiple files out of the box without any fancy script voodoo. However a Java update broke the software and there was much pointing of fingers and little solving the problem. They have probably fixed the problem by now but I have moved on.