Author Archives: pzearfoss

This? You just need to watch this.

Greg Wilson – What We Actually Know About Software Development, and Why We Believe It’s True from CUSEC on Vimeo.

Advertisements

A Cool KVO Trick

A coworker of mine attended the Voices that Matter conference in Boston a couple of weeks ago and shared this idea about KVO observing from Mike Ash during his Defensive Programming talk.  He suggests supplying a static pointer to the context parameter:


static void *p = &p;

[someObj addObserver:self forKeyPath:@"aPath" options:NSKeyValueObservingOptionNew context:p];

// ...

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == p)
    {
        // do stuff
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

Seems like a lot of magic at first, but by specifying a context every time and using one that’s not only unique to your object but also to the file containing your subclass you can ensure that the message sent to you is actually for you and you avoid potentially stepping on the toes of your super class. Neat stuff! It’s also worth noting that checking the context pointer first is a super-fast way to see if you need to care about the observation method.

Side note: if you’re not subscribed to Mike Ash’s Friday Q&A blog (link above), you definitely should. I learn something new there every week.

Cappuccino : First Thoughts

Hello to all the readers coming from iDevBlogADay!  I’ve started working on a project that is being built using Cappuccino, a web development framework modeled off Objective-c and Cocoa.  After working with it for about 5 days I wanted to scribble down my first impression of the framework and tools.

Language:

The language for working with Cappuccino is objective-j.  Objective-j is to javascript what objective-c is to c in that you get object orientedness without it mucking up the foundations of the base language.  According to its creators, this is exactly why they chose the smalltalk style syntax of objective-c over other constructs when deciding how to craft their language.

Coming from iOS development, picking up the syntax was a breeze.  Having had a background with javascript didn’t hurt either, but I haven’t yet run across any particular problem where I’ve had to lean on that knowledge to move forward.  Some things are different though and might trip up would be adopters:

  1. No .h files – Javascript has no notion of separate compilation (or compilation at all for that matter).  As a result there is no .h file, only your .j which contains your @implementation block.  The @implementation block serves as both the @interface and @implementation from objective-c containing instance variables and full method implementations.
  2. No properties – I know there’s some haters of the @property directive in the community.  To those folks, I don’t know how you ever lived without dot syntax, as it’s the one thing I miss from objective-c.  Typing things like [[[self view] subviews] objectAtIndex:0] and the like gets a bit tedious after a while.  That said, you can still have objective-j generate accessors for you with the @accessors directive.    Why the lack of dot syntax?  For the same reason objective-j was chosen: not breaking javascript.  Javascript is object oriented in its own way, so supplanting its existing dot syntax would break the language.
  3. Variable naming – iVars in the interface are still named with their type, but without the ‘*’ or pointer to it.  Local variables cannot be typed (probably what still trips me up the most).  The keyword for a local variable is “var” from javascript syntax.  All this really means is that you need to be extra careful naming variables so you know what they are later in code.

Frameworks:

I can’t help but be impressed with how thorough the Cappuccino folks have been in duplicating the Cocoa frameworks.  Virtually all the foundation classes you might need are there as well as much of the Cocoa UI components.  This is probably the greatest benefit to using Cappuccino is the sheer number of controls available out of the box without having to get into the nitty gritty of HTML and CSS manipulation required to get things like scrolling table view and outline views.  Cappuccino keeps the API to very close to their Cocoa counterparts so using them is easy if you’re already familiar.

Installing:

To get started learning Cappuccino provides a starter package that let’s you play around with the frameworks.  For a full fledged installation, the simplest thing is to build the frameworks from source.  There’s an installation script that will download the sources and compile them.  The included jake tool (think make, but for javascript) makes it very simple to build all the frameworks you need and deploy your application later.  All this work is done on the command line, so you’ll want to be comfortable in terminal before you dive in.

Development Tools:

This is probably where Cappuccino is lacking the most at the moment.  There is an Xcode plugin but I’ve found it’s crashy and unreliable in Xcode 4.  So far the best set of tools I can find are TextMate and Xcode’s Interface Builder with XCodeCapp which converts the xib files to cib (Cappuccino interface files) on the fly.  Coda has support for objective-j though I haven’t tried it out yet.

Debugging has its own set of challenges as well.  It’s supposedly possible to set breakpoints in either firebug or safari’s web developer window, but I haven’t seen how to do that yet.  So far console.log has been my best friend for debugging my application.  Additionally, since there is no compiler you don’t get the benefit of compiler errors and warnings to help you along.

I’m hoping the state of the tools improves as Cappuccino chugs closer to 1.0.  I’d love to see a full blown Xcode plugin with code completion, debugging, and building and deployment.  That is a tall order of course, especially when Xcode itself sometimes feels more like a beta than a fully tested application.  280North, the team behind Cappuccino seemed to have something strong going with Atlas, a web based interface builder and IDE, but there hasn’t been any movement on that since they were bought out by Motorola a couple of years ago.

Results:

Tools aside, the amount you’re able to produce with very little code (especially if using interface builder) is pretty profound.  Having worked on web applications in the past it’s refreshing to be able to focus on the logic of the app rather than being worried about the ins and outs of HTML, CSS, and raw javascript.  Cappuccino seems to make intelligent decisions about how rendering a given view should be handled, whether with a div or HTML 5 canvas.  Having a proper abstraction for the DOM is invaluable in this regard and most of the default controls look great right out of the box.

Conclusion:

If nothing else it’s fantastic to be able to use my objective-c skill set and jump into developing a modern web application quickly using cappuccino.  It requires you to develop your own workflow; it’s not as integrated as iOS / Xcode is.  The tools, however, seem to be improving as the Cappuccino approaches 1.0.  In all, I left web development because I didn’t like having to deal with both the application logic and HTML/css drudgery simultaneously to get anything done.  Cappuccino solves that problem for me and has allowed to me to produce some promising stuff very quickly.

Onward to Objective-J

I’ve starting working on a web project that will be built around objective-j and cappuccino, a an objective-c/cocoa style layer above Javascript. There’s some interesting challenges to go along with it, especially as it’s a new platform and I’m relatively unfamiliar UIKit’s older brother, AppKit. I’ll be posting a lot of about it in the next couple weeks as this project rolls on.

As a new platform, (good) documentation is pretty scant. Here’s a couple of links where you can learn more and get started.

Cappuccino Homepage
Github repo (don’t follow these install instructions, they didn’t really work for me).
THE tutorial that actually helped me get it installed.

Much of the install process requires you be at least pretty comfortable on the command line. Additionally you’ll want to create .bash_profile file in your home directory if you don’t already have one since there are a couple environment variables the installer will want to create. Overall the framework looks like it’s pretty simple to get rolling for someone like me who’s used Javascript in the past but has spent the past couple years in objective-c. Lot’s more to come!

Markdown on MacOS

Readown is a markdown viewer for MacOS. I couldn’t get it to open .markdown files on my machine after downloading the binary, so I grabbed the source from github and rebuilt for Lion which seemed to solve the issue. I’m posting it up here thinking it may help someone else. Cheers!

Updates to PZIndexedArray

I posted another update to PZIndexedArray that fixes some bugs with sorting and key deletion as well as some greater conveniences for checking keys and lack thereof.

It’s up on GitHub as always.

Getting the Tail Truncated Version of a String

Most of the iOS controls have the option to tail truncate a string with an ellipsis on the end. You can even get this same functionality when drawing a string yourself. However, there doesn’t seem to be a way to get the tail truncated version as an NSString.

iOS Developer Tips has a nice little category do get exactly that. It allows you to specify the width and font used and will return you the truncated version. Very handy! The code for it is located here.

IndexedArray Updated

I updated the IndexedArray project from yesterday with some fixes and support for NSCopying. You can find it here.

A Better Table View Data Structure

Lately, I’ve found myself creating a lot of table views that look like this:

Grouped Table View

Grouped Table View

A plain-jane table view filled with homogenous items grouped by some common element.  I couldn’t help but notice how ill-suited the standard NS data structures are for handling this.  It always involves some sorted array containing the keys of a dictionary which is filled with sorted arrays.  The setup for these is pretty standard and easily repeatable, so I submit to the community my IndexArray class which takes care of much of the boiler plate for you.  This is definitely rough around the edges as I only started putting this all together yesterday.

First some high level requirements:

  • Everything should be sortable: keys and items.
  • I want to be able to add and remove items without having to always resort.
  • I want to be able to specify how the sort should occur.  I want this to be as convenient as sorting an array.
  • I don’t want have to worry about the logic of whether a key has an array associated with it when I push items into it.
  • Items should be easily accessible by index so it works rather seamlessly with UITableViews.
  • Keys should have the same freedom as they do in NSDictionary.

Here’s my public interface as it stands now:


@property (nonatomic, assign) SEL keySortSelector;
@property (nonatomic, assign) SEL objectSortSelector;
@property (nonatomic, copy) NSComparator keySortComparator;
@property (nonatomic, copy) NSComparator objectSortComparator;

// accessing keys
- (id)keyAtIndex:(NSUInteger)index;
- (NSOrderedSet *)allKeys;
- (NSUInteger)keyCount;

// accessing objects
- (id)objectForKeyAtIndex:(NSUInteger)keyIndex objectIndex:(NSUInteger)objIndex;
- (id)objectForKey:(id)key index:(NSUInteger)index;
- (NSArray *)allObjectsForKey:(id)key;
- (NSUInteger)count;

// adding objects
- (void)addObject:(id)object forKey:(id<NSCopying>)key;

// removing objects
- (void)removeObject:(id)object forKey:(id)key;

You can see that I’ve specified 2 ways to sort keys and items.  Since keys are usually strings, it’s uber convenient to simply hand the compare: selector to the data structure.  For what I’ve been working on the items are NSManagedObject subclasses, so I need something a little more powerful to maintain their order, so I can also send in a comparator block in the form:


typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);

Adding and removing objects is as simple as possible with:


// adding objects
- (void)addObject:(id)object forKey:(id<NSCopying>)key;

// removing objects
- (void)removeObject:(id)object forKey:(id)key;

Under the hood:

Here’s the rest of the interface:

@interface PZIndexedArray : NSObject
{
    @private
    NSMutableDictionary *dictionary_;
    NSMutableOrderedSet *orderedKeys_;
    
    SEL keySortSelector_;
    SEL objectSortSelector_;
    NSComparator keySortComparator_;
    NSComparator objectSortComparator_;
    
    BOOL sortsKeys_;
    BOOL sortsObjects_;
    BOOL usesComparatorForKeys_;
    BOOL usesComparatorForObjects_;
}

I’m using two data structures inside the class. First an NSDictionary that will contain mutable arrays for each key. Secondly an NSOrderedSet that will also contain every key. The ordered set will guarantee uniqueness of the keys and provide the ordering I need.

You can also see the selectors and comparators being stored. There’s also some flags to know whether the class should try to sort at all (we won’t if there’s neither a comparator nor a selector). In the implementation as I have it, the selector will take precedence over the comparator if both are provided for either keys or items.

The implementation is pretty straightforward. Setting a comparator or a selector automatically triggers the flags for sorting. There’s a setter for each one, but they all look basically like this:

- (void)setKeySortComparator:(NSComparator)keySortComparator
{
    if (keySortComparator != keySortComparator_)
    {
        [keySortComparator_ release];
        keySortComparator_ = Block_copy(keySortComparator);
    }
    
    sortsKeys_ = keySortComparator != nil;
}

Adding an object for a key is pretty simple. The mutable array is automatically created if no entry exists for a key.

// adding objects
- (void)addObject:(id)object forKey:(id<NSCopying>)key
{
    NSMutableArray *array = [dictionary_ objectForKey:key];
    if (!array)
    {
        array = [NSMutableArray array];
        [dictionary_ setObject:array forKey:key];
        
        if (sortsKeys_)
        {
            [self insertKeySorted:key];
        }
        else
        {
            [orderedKeys_ addObject:key];
        }
    }
    
    if (sortsObjects_)
    {
        [self insertObject:object array:array];
    }
    else
    {
        [array addObject:object];
    }
}

If there’s no sorting the on the keys, the key simply added to the set, otherwise it gets inserted in sorted order. Same goes for items. The sorted insert methods are pretty much the same both. The basic method is to iterate through the array until the object in the enumerator is greater than the object being inserted.

- (void)insertKeySorted:(id)key
{
    if ([orderedKeys_ count] == 0)
    {
        [orderedKeys_ addObject:key];
        return;
    }
    
    __block NSUInteger insertIndex = -1;
    __block NSInvocation *selectorInvocation = nil;
    if (!usesComparatorForKeys_)
    {
        selectorInvocation = [NSInvocation invocationWithMethodSignature:[key methodSignatureForSelector:keySortSelector_]];
        [selectorInvocation setTarget:key];
        [selectorInvocation setSelector:keySortSelector_];
    }
    
    [orderedKeys_ enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if (idx  < [orderedKeys_ count])
        {     
            NSComparisonResult result = NSOrderedAscending;
            if (usesComparatorForKeys_)
            {
                result = self.keySortComparator(key, obj);
            }
            else
            {
                [selectorInvocation setArgument:&obj atIndex:2];
                [selectorInvocation invoke];
                [selectorInvocation getReturnValue:&result];
            }
            
            if (result == NSOrderedAscending)
            {
                insertIndex = idx;
                *stop = YES;
            }
                                
        }
    }];
    
    if (insertIndex == -1)
    {
        [orderedKeys_ addObject:key];
    }
    else
    {
        [orderedKeys_ insertObject:key atIndex:insertIndex];
    }
}

The result is adding items from an array into this data structure is much more compact and cleaner than maintaining the data structures yourself:

IndexedArray *byName = [[IndexedArray alloc] init];
byName.keySortSelector = @selector(compare:);
byName.objectSortComparator = ^NSComparisonResult(Document *doc1, Document *doc2) {
    return [[doc1.filename firstCharacterAsString] compare:[doc2.filename firstCharacterAsString]];
};
// firstCharacterAsString is a category I created.  

And it integrates nicely with the table view datasource methods:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [categoryIndex keyCount];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [categoryIndex allObjectsForKey:[categoryIndex keyAtIndex:section]];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [categoryIndex keyAtIndex:section];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *identifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
    }
    
    id item = [categoryIndex objectForKeyAtIndex:indexPath.section objectIndex:indexPath.row];
    cell.textLabel.text = [item filename];
    return cell;
}

The code for this is posted up GitHub. Please have a look and feel free to contribute back!

Roman Numerals in iOS

For a recent project I needed to create a table view where items were listed alongside roman numerals.  I surprised that I didn’t find any open source component for doing this, so I created this category on NSNumber that returns its roman numeral value as a string.  Since I translated the code from a .net implementation I found in a tutorial, I figured I may as well contribute it back.

Happy Coding!