Dynamic Objective-C for Rubyists

A lot of Rubyists still think Objective-C is the Devil’s language, full of compiler errors and terrifying memory management and other such infernal nonsense. And they’d be right. But what many of them don’t realize is that Objective-C is like your friend’s sexy sister – it’s got all kinds of hot moves, even if it is a little off-putting and the family resemblance a bit unsettling.

I’ll do my best to Enumerate (ha!) the dynamic similarities between the languages. If I’ve missed something, let me know!

Dear Objective-C object: can I send or __send__ you a message?

Why yes you can. Simply call performSelector with up to two extra parameters:

[obj performSelector:@selector(myMethod)];
[obj performSelector:@selector(myMethod) withObject:myParameter];
[obj performSelector:@selector(myMethod) withObject:myParameter withObject:anotherParameter];

You can also get a little funky and mess around with threads and delays. These are especially useful if you want to keep your UI updating (such as updating a progress bar while searching for data). Simply use the following:

[obj performSelector:@selector(myMethod) withObject:myParameter afterDelay:2.0];
Shouldn’t I make sure the object understands the method? You know, Ruby has this respond_to? method…

Wouldn’t you know it, Objective-C has nearly the same method:

SEL dubiousSelector = @selector(dubiousMethod);
if ([obj respondsToSelector:dubiousSelector])
  [obj performSelector:dubiousSelector];
What if I want to construct messages at runtime? I can’t exactly do that with @selector.

Don’t worry – Cocoa provides many convenience functions, including NSSelectorFromString, which will allow you to create messages willy-nilly:

SEL willyNillySelector = NSSelectorFromString(aString);
[obj performSelector:willyNillySelector];
But let’s say I want to get extra freaky with my methods. In Ruby I can use method_missing to catch any message…

Thanks to Ruby and Objective-C’s shared ancestry of the much-lamented SmallTalk language, you can accomplish dynamic message processing in either. It’s a bit trickier in Objective-C (specifically Cocoa), but it can be done by defining forwardInvocation.

And wouldn’t you like to know how it works? I would too! But I need to read a little more about it! So stay tuned, ‘cuz just like the subject matter, this blog is Dynamic! Ha! Get it!

Messages are great and all, but what if I want to mess with method implementations themselves? I can simply define_method it up in Ruby…

No problem – the Objective-C runtime has all kinds of fanciness for messing with class and object innards. Although you can’t yet create closures at a whim, you can still switch around implementations.

Note: you should always import the following header when utilizing runtime functions:

#import </usr/include/objc/objc-class.h>

Some functions you might be interested in for messing around with methods are:

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
IMP class_getMethodImplementation(Class cls, SEL name)

They each require some or all following information:

  • The class being modified. To modify instances of the class, you’d pass
    [MyClass class]
    in; to modify the class itself, you’d pass
    [MyClass class]->isa
  • The selector (method name) being updated
  • A Method Implementation (type ‘IMP’), which is just the compiled code that underlies a given method
  • A string (technically a C character array, so don’t prepend an @ symbol to it) containing the types of the method signature. The first character represents the return type (”v” for void, “@” for object references, etc.; those are the most common you’d use, but there’s a list of type encodings you can refer to for more). The second and third should always be “@:”, representing an internal necessity. Any other characters are used to represent the actual argument types.

You probably figured out that the easiest way to define a method implementation (IMP) is to use class_getMethodImplementation. That way, you can do something like the following:

IMP myMethodImplementation = class_getMethodImplementation([MyClass class], @selector(methodWithArg:andArg:));
class_replaceMethod([OtherClass class], @selector(otherMethodWithArg:andArg), myMethodImplementation, "v@:@@");

If that seems a little complex, don’t worry – it’s easy enough to boil it down into a convenience method:

#import </usr/include/objc/objc-class.h>  

void SwizzleMethod(Class destClass, SEL destSelector, Class origClass, SEL origSelector, BOOL isInstanceMethod) {
  Method dMethod = class_getClassMethod(isInstanceMethod ? destClass : destClass->isa, destSelector);
  Method oMethod = class_getClassMethod(isInstanceMethod ? origClass : origClass->isa, origSelector);
  if(!class_addMethod(isInstanceMethod ? destClass : destClass->isa, destSelector, method_getImplementation(oMethod), method_getTypeEncoding(oMethod)))
    method_exchangeImplementations(dMethod, oMethod);
}

// Example instance method usage:
SwizzleMethod([NSString class], @selector(length), [MyClass class], @selector(customLength), YES);

// Example class method usage:
SwizzleMethod([NSString class], @selector(string), [MyClass class], @selector(customCreator), NO);

You can put the SwizzleMethod function into a file and include it globally in your prefix header (usually named something like MyProject_Prefix.pch).

How about extending existing classes? I’d love to add some ActiveSupport-style convenience methods…

First of all, be sure to check out the Objective Support project, which accomplishes a lot of the goodness you’re used to from ActiveSupport.

Objective Support does its magic largely through the use of categories, which are a nice mixin-style feature of Objective-C. Essentially, categories allow you to “re-open” classes just like Ruby; you can create multiple categories for any given class and insert methods as you see fit. You can’t add instance variables, but you can override existing methods.

Thankfully, the implementation of categories is fairly simple:

/* Define the category's interface. In this case, we're
   re-opening NSString and calling our category "Utils" */

@interface NSString (Utils)
- (NSArray*) split;
- (NSArray*) split:(NSString*)delimiter;
@end

// Implement the category's interface
@implementation NSString (Utils)

- (NSArray*) split {
  return [self split:@","];
}

- (NSArray*) split:(NSString*)delimiter {
  return [self componentsSeparatedByString:delimiter];
}

@end

Note: you may want to include your category header in your prefix header (or at least the classes in which its methods get called), as otherwise you’ll see a bunch of “object may not respond to xxxx” warnings.

Neat-o! They should just call it “Dynamic-C”!

This is by no means an exhaustive list of Objective-C’s dynamism, but it covers a lot of the goodies. If there’s something I left off that you earnestly believe should be here, or you see a (gasp!) code error, let me know!


Individually Rounded Corners for your iPhone iPleasure

Everyone likes rounded corners (except Internet Explorer, but who cares?). By now, we’re used to simple declarations to get our hot sexy web 2.0 roundedness in Webkit and Firefox:

border-radius: 10px;

Or if you want to get really freaky, you can define radii individually for each corner (unfortunately this syntax varies by rendering engine):

-webkit-border-top-right-radius: 10px;
-webkit-border-bottom-left-radius: 20px;

Now, if there’s anything I’ve learned about developing for the iPhone, it’s that it takes 10 times as much work as web development. Rounded corners were no exception, until iPhone OS 3.0 released this little gem:

#import <QuartzCore/QuartzCore.h>
CALayer* layer = [myUIView layer];
layer.cornerRadius = 10.0;

Suddenly rounding corners on the iPhone was as easy as slicing bread. Yet there is no way to round individual corners like in a web browser, and much more importantly, using cornerRadius will kill your performance – especially on older devices. Sure, you can get by if you just have one or two rounded views and no scrolling, but we should haven’t to limit the glory of our rounded revolution, now should we?

Because I needed excellent performance with many simultaneous views as well as individually rounded corners, I opted to see what else I could come up with. Luckily, there were several examples on the interwebs with good techniques, though none gave me a simple way to round corners individually. So, after a little sweat, I came up with the following code for you, my dear readers, to use and nuture and love:

CGFunctions.h
//
//  CGFunctions.h
//  OccoTouch
//
//  Created by Mike Laurence on 1/11/10.
//  Copyright 2010 Punkbot LLC. All rights reserved.
//

#pragma mark -
#pragma mark Rounded Corners
void CGContextAddRoundedRect(CGContextRef context, CGRect rect, int inset, int ul, int ur, int lr, int ll);
CGFunctions.m
//
//  CGFunctions.m
//  RoundedCorners
//
//  Created by Mike Laurence on 1/11/10.
//  Copyright 2010 Punkbot LLC. All rights reserved.
//

#import "CGFunctions.h"

#pragma mark -
#pragma mark Rounded Corners

void CGContextAddRoundedRect(CGContextRef context, CGRect rect, int inset, int ul, int ur, int lr, int ll) {

    CGContextSaveGState(context);

    int xLeft = rect.origin.x + inset;
    int xRight = rect.origin.x + rect.size.width - inset;
    int yTop = rect.origin.y + inset;
    int yBottom = rect.origin.y + rect.size.height - inset;

    if (ul > 0) {
        CGContextMoveToPoint(context, xLeft, yTop + ul);
        CGContextAddArcToPoint(context, xLeft, yTop, xLeft + ul, yTop, ul);
    }
    else
        CGContextMoveToPoint(context, xLeft, yTop);

    if (ur > 0) {
        CGContextAddLineToPoint(context, xRight - ur, yTop);
        CGContextAddArcToPoint(context, xRight, yTop, xRight, yTop + ur, ur);
    }
    else
        CGContextAddLineToPoint(context, xRight, yTop);

    if (lr > 0) {
        CGContextAddLineToPoint(context, xRight, yBottom - lr);
        CGContextAddArcToPoint(context, xRight, yBottom, xRight - lr, yBottom, lr);
    }
    else
        CGContextAddLineToPoint(context, xRight, yBottom);

    if (ll > 0) {
        CGContextAddLineToPoint(context, xLeft + ll, yBottom);
        CGContextAddArcToPoint(context, xLeft, yBottom, xLeft, yBottom - ll, ll);
    }
    else
        CGContextAddLineToPoint(context, xLeft, yBottom);

    CGContextClosePath(context);
    CGContextRestoreGState(context);
}

(Full sample project)

This draws a path on your graphics context, which can then be used to draw outlines or fill with colors/patterns/etc.

Notes:

  • Because CGContextAddRoundedRect is defined as a function and not a method of some class, you’ll need to do a little configuration to get your compiler to accept it. Mainly, find your project’s precompiled header file (it should be called something like ProjectName_Prefix.pch) and insert the following line:

    #import "CGFunctions.h"

    That will allow you to use the function anywhere in your code.

  • Watch out for the stroke going outside the view rectangle – you may get weird, uneven-looking drawing. I’ve provided an “inset” parameter in the CGContextAddRoundedRect function so that you can avoid just that. A good rule of thumb is to provide the same value to the inset as you do to your stroke width (you may know it as line width, set via the CGContextSetLineWidth function).

Here’s a simple example of using CGContextAddRoundedRect in practice:

- (void) drawRect:(CGRect)rect {
    // Get graphics context for this view
    CGContextRef context = UIGraphicsGetCurrentContext();
   
    // Set our fill color
    [fillColor set];
   
    // Add the path and fill. Note that our inset parameter (3rd param) is equal to our stroke width.
    CGContextAddRoundedRect(context, rect, strokeWidth, upperLeftRadius, upperRightRadius, lowerRightRadius, lowerLeftRadius);
    CGContextFillPath(context);
   
    // Set our stroke color
    [strokeColor set];
   
    // Set our stroke width
    CGContextSetLineWidth(context, strokeWidth);
   
    // Add the path again and fill
    CGContextAddRoundedRect(context, rect, strokeWidth, upperLeftRadius, upperRightRadius, lowerRightRadius, lowerLeftRadius);
    CGContextStrokePath(context);
}

In addition to painting, you can also use paths to mask images and do all kinds of other fun stuff with Quartz (check out this article for some sample image masking code).

That ought to get you started. Now, go forth and spread the rounded corner love!


All Your Blog Are Belong To Project52

I’ve officially joined Project52, a collective challenge for blog writers to write one post every week for an entire year. It was originally envisioned as just a little competition among 20 or so friends, but it’s recently exploded past the 700-member mark (more proof that word-of-mouth is the best – and freest – form of marketing).

The idea of required artistic responsibility (otherwise known as “The Deadline”) is new to no one, and yet we often forget how potent it can be. There’s a reason we all wrote so many papers in college – we had to. (Or, in some cases, bought them from shady websites… I speak of other people, of course. I was nowhere near shady. More on the sunny side.) In fact, I recently had an eye-opening experience with deadlines while developing shortcts.in with three friends at an overnight hackathon. The goal was to develop a web application in approximately 24 hours, and in doing so, I had perhaps the best team development experience of my life. “Agile” took on new meaning as we reached maximum velocity and cast aside the time-wasting “planning” phase in favor of pure, delicious implementation. As my team member Dave said at the time, “Why discuss when you can just do?” Well, I may be paraphrasing/alliterating that for the sake of epic impact, but the idea was clear. We would have missed out on that sublime clear-mindedness had we not had a ridiculous deadline looming over our head.

Let’s just say that that having time is inversely related to productivity. Really, We should all be doing Project365. Then again, sometimes you just have to stop working and play Dragon Age until 5am… not that I’ve ever done that, of course.


I’m Making An App For That

It’s funny how time flies when you’re a hermit cranking out code 10 hours a day, attempting to make something concrete but all the while watching your once rising Internet star (ha!) plummet like the Dow circa September ‘08. And now you’re just starting blog posts with vastly overused metaphors. Ah well.

But hey, I made an iPhone app! It’s called iPose, and it features, amongst other things, scantily-clad ladies.

I’m also nearly done with my next app, Leap Quest! It is seventeen times more complex than iPose (*actual ratio of complexity more complex than 17 : 1), and is quite entertaining, if I may say so myself. It also has cutesy graphics that would be suitable for an 8-year-old (and no, I didn’t have to go door-to-door, Walter).

Based on my developmental progression, you might assume that my grand plan is to have 8-year-olds innocently obtain Leap Quest and then become interested in my brand, Punkbot, and then via the app store or my website accidentally stumble across aforementioned iPose scantily-cladness, thus prematurely exposing them to toxic American adult values earlier than they might have had they depended on discovering a hint of nipple through static on their friend’s satellite TV (wait, that was my generation. Today you can just google image search any two random words and visually feast on fetishes you’ve never even dreamed of!) But I don’t have grand plans. Only grandiose ones.

You know what? I rather like ranting. I wrote some “rants” as a sort of online humor column back in college, before there were “blogs”, which makes me kind of cool and iconoclastic, except it was also before “anyone cared”, so I wasn’t able to capitalize on that coolness. I should really return to my ranting roots. Maybe I will.

Anywho, I just thought you may have been wondering if there was An App For Cute Yellow Jumping Sun-Flower-Germ-Looking Dudes. There will be soon, so stay tuned. And check out this youtube trailer:


Quick, Convert Your RubyCocoa To MacRuby!

You won’t regret it. Really. MacRuby is like filet mignon, while RubyCocoa is just a sad, undercooked rumproast. Did I just paraphrase a joke from American Pie 2? You better believe it, buster.

Anyway, if you have a RubyCocoa project that needs a little bit of shininess, it may be surprisingly easy (and satisfying) to quickly port it over to MacRuby. I just spent about 4 hours converting a fairly sophisticated app (aside from its MIDI interface, which is a bit more tricky, but you probably won’t be dealing with that).

My first stop was this post, a very nice summary of the basic steps that need to be taken. However, I encountered quite a few additional snags, and I thought I’d post them just in case you, random internet denizen, want to skip them all together. Most of them are covered in the MacRuby docs, of course, but they’re here in a nice digestible table format so you can more easily knock out your conversion. Because as fun as prettying up your code is, you’d still rather be adding functionality, right?

Read the rest of this entry »

Apparently Apple’s App Store Databases Are So Complex That They Take 5+ Weeks To Update My Goddamn Name

You can be up and running on the App Store in 24 hours if you want to parade your apps around under your own name.

However, apparently the additional overhead of having a company name adds so much stress to Apple’s systems that you’re placed in a queue and told to be patient while your “updates” chug along for FIVE weeks. And COUNTING.

So, developers be warned – think of your company name NOW, file for an LLC, and submit for an account (or conversion of an account, like I did) before you even begin programming. Because sitting around for weeks with a ready-to-go application sucks.

Also, definitely telephone the developer connection if you need to convert from an individual to company account. Don’t just send them an e-mail. I did that at first, and I never in three weeks even received a response. I had to actually call in to get things rolling (and then I had to *fax* my business documents in. What is this Apple, 1984? I thought you were running in slow motion and throwing objects through large oppressive screens?)

Your mobile device has encountered an unexpected error (0xE8000001)

If you’re building & deploying apps to your iPhone, you may encounter this dreaded and shamefully unhelpful error message at some time. It’s happened twice to me; the first time, after scouring the Internets for answers, it looked like I only had a couple of choices: either jailbreak my iPhone and do some SSH trickery or restore to a previous version. I went for restoring, and it was even more irritating than I thought it would be.

But you don’t have to restore your phone, and you don’t need to jailbreak, either; just change the application’s package identifier:
com.initech.jumptoconclusions
=>
com.initech.jumptoconclusions2


The hidden problem (as explained by the post linked to above) is that there are broken bits of your app hanging around in an inaccessible folder on the iPhone. However, if you change the package name, it will use a different folder for deployment, so you will no longer be dealing with the broken parts.

Of course, if you’re really sold on that initial app identifier, then you’ll have to restore or jailbreak eventually. But maybe by the time your app is ready to send off to the Committee of Endless Deliberation, you’ll be on the next OS, and it will have some sort of automatic cleanup to deal with this issue. I mean, it had better.

Dancing Girl Will Sell Your Miscellaneous Product Like Hotcakes

No matter what you’re selling, dancing girl will make it happen.

dancing_advertisement_girl

Wordpress to the Rescue

Last year, I embarked on a mission – to code my own blog software so I could say that I coded my own blog software. My hubris got the best of me, though, revealed in a severe lack of friendly blog editing, which kept me from writing the fancy words that I know my internet readers crave. As a result, I decided to shake things up a bit and install wordpress. It’s – shudder – PHP, but sometimes ol’ Personal Home Page (yes, that’s its etymology!) fits in quite nicely, like when you don’t want to manage a burly Rails stack. Which is All The Time in my case. Don’t get me wrong – I frickin’ love Rails, but as a programmer I’m just not terribly interested in administering anything at all. I can dream about load balancing and memcached server side includes all night, but at the end of the day I’d rather hand the reigns over to someone else (preferably a guy who wears a localhost shirt). I hope this means my writing juices began to flow again. I believe it’s my duty to flood the internet with as much inanity and alliteration as humanly possible.

Flex Benchmarks Are Fun For the Whole Family!

I’ve spent the last few months digging deep into ActionScript, the programming language for Adobe Flash Player. The result: I now have the power to create unspeakably irritating advertisement banners, surprisingly fun 2D physics-based games, and various charts of dubious usefulness. In the spirit of sharing, I now give you one of the latter: a smattering of ActionScript benchmarks in colorful, bubbly chart form.



This little project was originally inspired by a JavaScript benchmarking page I stumbled across, wherein the author quips “no one should care about JavaScript performance. But if you do, this page will help you get a feel for which operations are fast and which are slow.” Pretty much the same rationale applies here – unless you’re building a complex, cpu-intensive Flash game (like myself, hence my own interest), you don’t need to worry too much about outer static variable access taking a few microseconds longer than inner static variable access.

Usage: click ‘Test Iterations’ to perform each benchmarking action the specified number of times. Unless you’re on a very slow computer, even 150,000 should fly by fairly quick. On some pages, you can also click the ‘Auto Test’ button, which will incrementally test more iterations until it has a total duration of at least 100 ms, which should give you a decently accurate average duration (note that the number of iterations may be different for each benchmark). You can also hover over the individual bars to see more detailed statistics and the code performed in the iterations (typically without the loop code itself, with the exception of linked list iteration.) Also, feel free to right-click and select “View Source” to look at and/or grab the source code. As usual, the code is licensed under the Creative Commons Attribution-Share Alike 3.0 United States License.

Caveats: I’m still trying to build a better AxisRenderer so the benchmark groupings look more, er, grouped. The Flex BarChart can group (”cluster”) by default, but I haven’t found a native way to omit empty bars for unequal group sizes or display titles for all group members. Hopefully I’ll get that figured out soon, along with a staggered benchmarking engine so that you don’t have to wait for all the benchmarks to complete before the chart updates.

And naturally, I’ll be adding some more benchmark variations in the near future. Function calls *are* positively thrilling, after all…