Monday, August 27, 2012

Forward Iterators


Introduction
Objective-C and the libraries in the Cocoa framework provide us with iterators, however they are to be used traversing class containers (NSArray, NSSet, etc). When we need to use iterators to traverse a raw memory container of structs, pointers, or primitive types, then we don’t have any pre-built solution and most often have to use a custom implementation.
In this article we will see a simple way of using iterators to traverse a raw memory container of pretty much anything, without departing from the familiarity of Objective-C code. We will use a simple class derived from NSObject and delegation to implement a forward iterator.
Forward Iterator
Our sample code is very simple to understand, nevertheless once the concept is understood, it can be easily expanded to more complex scenarios. In our case we chose to create a structure to store time (hours, minutes, and seconds), and we allocated enough memory, using malloc, to fit 100 entries of such structure.
typedef struct {
    int seconds;
    int minutes;
    int hours;
} TimeStruct;

The iterator we implemented is a forward iterator. It starts iterating from the first element (element zero) in the raw memory space, and moves forward sequentially to the last one. It cannot be rewinded, thus it is only good to be used one time. After the memory space has been traversed by the forward iterator, the iterator should be discarded.
In its implementation our forward iterator declares a delegate protocol and requires 3 methods to be implemented by the delegated class. Those methods should return:
  • The number entries in the allocated memory.
  • A pointer to the allocated memory.
  • The size of an element within the allocated memory.
The implementation of our forward iterator and sample code can be found at GitHub. Clone and use it freely at:
$ git clone git@github.com:dcirne/ForwadIterator.git
We will be using modern Objective-C with ARC and automatic synthesis of properties in our code. Open main.m and see that all it does is to create an instance of DCSampleCode and traverses forward the memory container. DCSampleCode declared the struct above, populates its 100 entries, and implements the delegate methods of the DCIterator class. The iterator is implemented in the DCIterator class and uses familiar nomenclature for its methods, such as hasNext and next.
for (; [iterator hasNext];) {
    t = [iterator next];
    printf("%d - %02i:%02i:%02i\n", index++, t->hours, t->minutes
           t->seconds);
}

As you could see, our example is quite simple to understand, and you now can use this forward iterator with more sophisticated cases.