Tuesday, May 14, 2013

Simplifying UIKit Animations

The Problem

If you have ever worked with animations in iOS using UIKit you have most likely ended up with nested animation blocks and intractable code at some point. One of the problems that comes up is trying to chain multiple animations. You want animation B to run only after animation A has completed, and maybe then do something when animation B completes. This would look something like

[UIView animateWithDuration:0.25 animations:^() {
    // animation A
} completion:^(BOOL finished) {
    if (finished) {
        [UIView animateWithDuration:0.25 animations:^() {
            // animation B
        } completion:^(BOOL finished) {
            // Other code
        }];
    }
}];
And then you may want animations C and D to run after that, so much for clean code.

Another problem with this approach is that you can't easily switch or manipulate the animations. For instance you may want to run animation B after animation A in some cases and animation C after animation A in some other cases. Or you may want to dynamically change the properties of the animation like the duration.

Saturday, March 23, 2013

Delegate Multiplexing

The Problem

I have mentioned before how Cocoa is biased towards the delegate pattern. I argued that in some instances the observer pattern would be better suited. But in some cases the delegate pattern is the way to go.

Something you could argue as a limitation of the delegate pattern is the fact that there can only be one delegate. This criticism is not entirely valid because if you need more than one maybe you shouldn't be using the delegate pattern in the first place. But sometimes you are stuck with the delegate approach because that is how the a third-party framework (read Cocoa) was designed.

Here is a workaround for this limitation. The idea is to have a central delegate that dispatches messages to multiple delegates. I call this delegate multiplexing.

Wednesday, March 28, 2012

Syntax Highlighting in iOS

The Problem

One of the controls included with the UIKit framework of iOS is the UITextView. It handles all text editing tasks including line wrapping, copy and paste operations, and undo. The only thing it lacks is text styling. But starting from iOS 4.0 Apple added the CoreText framework. This framework gives you the ability to draw text with different styles and colors. The problem is integrating the text styling features of CoreText with the text editing features of UIKit.

The only successful reports of doing syntax highlighting involve either rewriting all editing features of an UITextView like in OmniUI, or using a UIWebView with JavaScript to handle the highlighting as described here and here.

I found a way of reusing a UITextView with custom drawing using CoreText.

Sunday, January 29, 2012

A* data structures

The Problem

A* (A-star) is the typical textbook algorithm: it is a simple concept and can be easily explained. It is also widely known, one of the first algorithms you learn in AI. But for some reason it is rarely implemented properly.

A* does a graph search minimizing the node expansions, therefore minimizing the search time, by using a heuristic function. The heuristic function gives an estimate of the distance from the current node to the target node. For instance if you are searching for a path between two points in a city, you can estimate the actual street distance with the straight-line distance. It will rarely be accurate, but it will be good enough of an estimate to considerably speed up the search using A*.

What A* does is expand the most promising nodes first, according to the heuristic function. In the city example it would choose streets which go in the general direction of the target first and, only if those are dead ends, backtrack and try other streets.

For a more in depth explanation of A* try the Wikipedia entry. You can find plenty of pseudo-code implementations. But the thing about pseudo-code is that it leaves out the details, which in this case is what makes or breaks the performance. For a fixed-size graph of size N and branching factor b, the worst-case complexity of A* is O(bN)...or is it? For most implementations out there the worst-case complexity is actually O(bN2) because at each node expansion they do a linear search of the open list (for example here, here and here).


Friday, January 7, 2011

Building Boost for iOS

Being a hard-core C++ programmer I have been trying for a while to get the full potential of the Boost C++ Libraries on the iPhone. The main problem is that Boost's build system does not fully support the iOS framework, so you have to do some hacking.

I looked at alternatives for a while and what I ended doing was using the Jam build files as reference to create an XCode project. You could also hack the build system to compile for the iOS without using XCode, but that seems to be a bit messy. Also, you need to worry about the different SDKs and about building separate versions for the simulator and device.

The advantage of having an XCode project is that you can step though the libraries in debug mode and don't have to worry about the particular versions since XCode will take care of that. So without further ado here it is: XCode project for Boost Libraries v1.44. You will also need to download the Boost sources version 1.44 and follow the instructions in the README file.

If you still want to have a compiled framework instead of having an XCode porject have a look at Building a Boost framework for iOS.

Sunday, December 5, 2010

Beware usigned integers

The Problem

I've always taken unsigned integers with a grain of salt. It's easy to forget you are dealing with an unsigned integer and then you do a signed operation and get an unexpected result. Take for instance this innocent-looking 'for' loop:

for (unsigned i = 9; i >= 0; i--)
  cout << i << " ";
It's not immediately clear that it's an infinite loop, but then you realize i is always greater than or equal to zero. On the plus side this is easy to spot when you realize your program is taking forever.

Some time ago I ran into a tricky unsigned bug while working in Objective-C. It took me a while to spot. See if you can spot it:

NSUInteger num1 = 4;
NSInteger num2 = 9;
NSInteger max = MAX(num1 - num2, 0);
NSLog(@"MAX(%i, %i) = %i", num1 - num2, 0, max);
If you run this you will get
MAX(-5, 0) = -5

Monday, November 8, 2010

Tabs vs. Spaces

...or why tabs are better than spaces for code indentation. I figured I'd have a say in the tabs vs. spaces war. Without a doubt there is no silver bullet, but I believe tabs are better suited for indentation (not for alignment, though). Here's why:

  1. One indentation level, one character. It's only natural. It is a perfect use of the tab character. As a matter of fact I haven't come across any other use (except maybe in plain text tables). It should be renamed to 'indentation character'.
  2. You can configure your preferred indentation width. No need to tolerate the aberrant n-character indentation used by your coworker.
  3. It's easier to search and replace. Want to find lines with an indentation level of 4 or more? No problem, just search for four tab characters. Done.
  4. No ambiguity as to the indentation level of a particular line: n tabs, n indentation levels.

Some clarifications. Note that tabs should be used for indenting, not for aligning. If you are looking to align code, have a look at elastic tab stops. Neither tabs or spaces are well-suited for alignment but if you have to choose one, choose spaces.