Easy and fast XML node access with TBXMLEx

I recently added a very nice feature to one of my Open Source projects, TBXMLEx, which is the possibility of directly access any node without having to loop through all its parent nodes. This is very useful when you know beforehand where the node is located at. The sintax is very clean and concise. Suppose you have the following XML:

NSString *xml = @"<data> \
        <a> \
            <a1/> \
            <a1/> \
            <a1/> \
        </a> \
         \
        <b/> \
        <b/> \
        <c/> \
         \
        <d> \
            <d1> \
                <d11/> \
                <d21/> \
            </d1> \
             \
            <d2> \
                <d21/> \
                <d22> \
                    <d221/> \
                </d22> \
            </d2> \
        </d> \
    </data>";

and that you need to access the “d221″ node, which is pretty deed inside the structure. Using TBXMLEx it is straightforward do to so:

TBXMLEx *parser = [TBXMLEx parserWithXML:xml];
NSArray *result = [parser.rootElement query:@"/d/d2/d22/d221"];
TBXMLElementEx *element = [result objectAtIndex:0];

The key point in the previous code sample is the “query” method (a member of TBXMLElementEx), which takes a path as argument and returns all nodes that matches the criteria, as TBXMLElementEx instances. Right now it supports only simple expressions, but nevertheless it’s a quite useful feature .

You may wonder why not use XPath instead. The point is, while very powerful, you’ll need extra libraries to work with XPath, and it can take some time to master its syntax. The “query” method I implemented does not intend to take over XPath nor reimplement its features, it is just a convenient, syntax sugar method to do regular tasks we face on a daily basis, and while someday it may be improved to be more powerful, XPath will always be the choice when you need to do nasty thigns with XML.

TBXMLEx is an Open Source library freely available at https://github.com/rafaelsteil/tbxmlex

A useful UIView addition via Categories (Objective-C, iOS)

One thing that makes me surprise even in 2011 is how many Objective-C developers completely ignore (or misuse) the power that Categories in Objective-C give to you. In other words, Categories allows you to do almost any sort of customization to any given class, especially those from the official SDK, which can be of huge help to save a lot of typing and making your code more readable.

One good example is view location and size handling, a task that every Objective-C developer does a lot. And I mean it. Objective-C can be extremely verbose to do some very simple and laboral tasks, like creating and positioning views on the screen, as well manipulating them. Take the following as example:

UIView *v = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 20, 10)];
v.backgroundColor = [UIColor redColor];
[self.view addSubview:v];

// Change only the X
CGRect frame = v.frame;
frame.origin.x = 90;
v.frame = frame;

// [....]

// Later, if we want to change the width, do it all again
CGRect anotherFrame = v.frame;
anotherFrame.size.width = 200;
v.frame = anotherFrame;

// And so on

While this is a practical, very common and working code, it can get repetitive and boring very fast, as the need to change any property of the view’s frame arrises, because we can’t simply do

v.frame.origin.x = 90;

as the compiler would complain. Instead, we first need to assign the frame property to a temporary variable, change it, and then assign it back to the target instance. Do this a series of times and you’ll be willing to pull your hair off. (I do). So how do we make it better? By using Categories, of course. What we want to accomplish is the following:

v.x = 90;

// .....
v.width = 200;

// And so on

As you can see, the different is that, instead of writing three lines of code for every single property we might want to change, we write just one. Below you find the Category code for this UIView addition:

@interface UIView (FrameAdditions)
@property float x;
@property float y;
@property float width;
@property float height;
@end

@implementation UIView (FrameAdditions)
-(float) x {
	return self.frame.origin.x;
}

-(void) setX:(float) newX {
	CGRect frame = self.frame;
	frame.origin.x = newX;
	self.frame = frame;
}

-(float) y {
	return self.frame.origin.y;
}

-(void) setY:(float) newY {
	CGRect frame = self.frame;
	frame.origin.y = newY;
	self.frame = frame;
}

-(float) width {
	return self.frame.size.width;
}

-(void) setWidth:(float) newWidth {
	CGRect frame = self.frame;
	frame.size.width = newWidth;
	self.frame = frame;
}

-(float) height {
	return self.frame.size.height;
}

-(void) setHeight:(float) newHeight {
	CGRect frame = self.frame;
	frame.size.height = newHeight;
	self.frame = frame;
}
@end

Save this code in any file, like UIView+FrameAdditions.(m|h), include it in your project, and you are good to go!