On indie iOS and Mac development.

Archive for the ‘Cocoa’ Category

My Thoughts on RubyMotion

Monday, May 7th, 2012

RubyMotion was announced this past week. In my world view, creation is better than talk, and there is no doubt that the developers of RubyMotion should be congratulated for shipping something. That’s more than a lot of people do and is worthy of great respect.

That said, my initial reaction was less than enthusiastic and received a fair amount of push back from my Twitter followers. To summarize my opinion, I feel that although it’s an admirable effort, and worthy of congratulations, I simply cannot recommend to new developers coming to the platform that they use a technology such as RubyMotion to build apps for iOS.

Sadly, 140 chars is simply not enough to lay out my reasons for this opinion, so instead, I thought I’d save up my thoughts and lay them out in a blog post. If you are a fan of RubyMotion, or MacRuby, then I’ll save you the effort of reading: Use them if they work for you, but in my opinion, it would be less effort to simply learn Objective-C.

What is RubyMotion

RubyMotion is a toolchain which enables you to write apps for iOS using Ruby. The toolchain interfaces directly with Cocoa Touch, so you still use the same Cocoa Touch API, but you use it through Ruby. Apps are created on the command line, and developers may, in fact are encouraged to, avoid Xcode altogether. RubyMotion is built on MacRuby, which, unlike the long-since-retired Java/Objective-C bridge uses the same runtime as Objective-C, so it has the advantage of always having access to the latest library APIs as soon as they ship. There is no need for the MacRuby distribution to track OS updates in lock-step motion.

So if you’re a Ruby developer who doesn’t know Objective-C, then this is great, because you get to program for the latest, hottest platform without having to deal with all that messy, icky Objective-C stuff.

Well, almost…

Keeping up to date

My experience in the past with technologies like RubyMotion is that they have difficulty staying up to date. When I pointed this out on Twitter, several people took issue with this assertion, rightfully claiming “But it’ll always be up to date with whatever the frameworks give you!” To which I say, “That’s not the stuff I’m worried about being up to date with!”

Ruby is a moving target

First, Ruby itself is a moving target, and Mac OS X doesn’t always ship with the latest greatest stuff. So this means you’re going to be always compiling and upgrading Ruby every time you update your OS. I have never seen a community so fond of deprecation as the Ruby community seems to be. Granted, tools like rvm and the like make this job a bit easier, but it is an additional level of complexity that can be a hassle.

Objective-C is a moving target

The bigger issue, I think, however, is that Objective-C is an actively growing language. Not just at the framework level, which is what most of the RubyMotion fans point to when they talk about compatibility, but also at the lower syntax level. Blocks, for example, are a very recent addition to the language.

RubyMotion can’t help but fall a bit behind when low level features like blocks are added to the Objective-C language. Although it’s easy to criticize Objective-C and talk about how it’s only adding features Ruby has had for years, that’s irrelevant. The point is that supporting new language features like this will always take effort and modifications to RubyMotion. Since Apple has (presumably) more engineers working on improving Objective-C than RubyMotion has on improving RubyMotion, that means that RubyMotion will always be slower to adopt new language features than Objective-C is in adding them.

Debugging and tools

I’ve written full apps using PyObjC and other technologies similar to RubyMotion. When I did, I inevitably reached a point where my frustration would get the better of me. Surprisingly, it was usually a result of having to debug the code I’d written in Python or Ruby.

Say what you will about gdb and lldb, they are still both lightyears ahead of their ruby equivilents. The same goes for the profiling tools that Apple provides. Scripting language advocates like to promote the idea that although their languages may be slower than compiled code, you can always redo slow portions of your code in C, C++, or in our case, Objective-C. The problem, however, is the tools to find out what portion of your code is slow are absolutely horrendous. Compare them to Instruments, which is a spectacular profiling tool by any measure, and you’ll see what I mean.

Xcode has its detractors, the RubyMotion developers among them, but whether you like Xcode or not, it is the designated tool that Apple has blessed for doing iOS development. Apple invests a substantial amount of R&D in this tool, and it’s ridiculous to think that it’s going to stay where it is. In fact, I would expect some of the upcoming improvements to iOS development to come in the form of more GUI oriented tools. A recent example of this is the introduction of StoryBoards. Imagine when tools like this become available!

Now, it’s fine and dandy if you’re a neckbeard and you eschew all GUI tools in favor of your l33ta55 vi/emacs skillz. I totally appreciate how amazingly productive you are with your hotkeys that let you do everything without moving your hands from the keyboard. I’m sure you’ll have a wonderful old age with your fingers curled and umoving thanks to RSI. What you don’t realize is that having a variety of movements (ie: going back and forth to the mouse occaisionally) while slower, is actually a healthier way to work. I know this because I was once you. I used to use emacs for everything, and command line for everything. And I had the wrist pain to prove it. Since I switched to Xcode and using more GUI tools, my wrist pain has totally disappeared.

Regardless of that, however, the key takeaway here is that overall, the tools provided by Apple are the best for what they do, will continue to improve, and may even, in the future, negate whatever perceived improvement you’re getting from using a higher level language. In fact, I’d go so far as to say that, Xcode aside, even Instruments, llvm, and lldb provide enough value today to make the gains you get from a higher level language irrelevant.

Not having to learn Objective-C

Finally, the big one.

I’m going to put this in bold here so it stands out and you remember it. It may be the most important part of this blog post. Here it is:

If you think that using RubyMotion is going to make it so you don’t need to learn Objective-C… you are wrong.

Remember up above where I said that RubyMotion uses the same runtime and Cocoa Touch API as Objective-C? Well guess what that means?

That means that the vast majority of the difficulty in learning to program for iOS, that is, learning the Cocoa Touch API, is still gonna be there for you… but now, thanks to the fact that you’re using a non-standard language to do it, you won’t be able to directly use any of the huge amounts of already existing sample code, courses, or reading material available across the Internet.

Instead, you’ll need to learn the ins and outs of Objective-C just to translate those examples into something you can use and then figure out how to use it from Ruby, because, it’s not gonna feel like straight up Ruby. It’s gonna feel like some weird amalgamation.

In fact, you’ll probably need to know Objective-C and the Cocoa Touch API better than a newbie Objective-C programmer, because you really will need to understand the code. Newbie Objective-C coders can probably get by just cutting and pasting, but you’ll need to translate it.

That’s harder than you might think.

Conclusion

So the point here is that the benefits of using a language and toolset other than Objective-C for iOS development simply are not there.

Please don’t get me wrong, I love Ruby, I love Python, I’ve written thousands of lines of code in them. In fact, my affair with Ruby started before I’d even heard of Objective-C! I started using Ruby in 2000. Yes, before Rails even. (Yeah, that’s right, I’m hip like that. @@ ) I think Ruby has it’s place, but iOS development isn’t it. Objective-C, Xcode, and Instruments are the right tools for that job. Similarly, Java is the right tool for Android. C# for Windows. Ruby or Python for server side scripting and automation. I think this is the only truly objective view that one can have.

My advice to new developers who want to write for iOS and who are on the fence about RubyMotion? In my opinion, don’t use it. Objective-C isn’t really that hard, and the fact that you already know a language (Ruby) will only make it easier. Saying you don’t like Objective-C based on superficial issues like brackets is simply xenophobia. You’re smart, you’ll get used to it.

My 10 Minute Review of PaintCode

Thursday, March 15th, 2012

The Internets are all atwitter about PaintCode. A new app which claims to allow you to draw shapes and graphics using their painting app and have it generate Objective-C Core Graphics code to display those same graphics in your iOS or Mac App.

Although PaintCode says that they’ll have a free demo out soon, a lot of indie developers like me are hesitant to invest $80 in a tool sight unseen. We all have been burned too often by magic code generating tools that were supposed to make our jobs SO much easier, but in the end, just hurt us by generating unmaintainable code that we didn’t understand. That said, I, being the selfless fellow that I am, decided to take one for the team, bought it, and well… here we are.

It should be noted that this is not the first app of it’s kind. Opacity by Like Thought can also, reportedly, generate Core Graphics code from drawings you do in it. I downloaded Opacity when I downloaded PaintCode, just so that I could be fair and balanced. I’m not going to focus too much on Opacity. They have a free demo, you can download it for yourself. However, in cases where I think a useful comparison should be made, I will do so.

First up… does it work?

Yep, it sure does. Its pretty damn cool.

PaintCode Main Window

You draw stuff in the window, and the code to draw that in Core Graphics appears in another panel below it. I really like this model. I like it because I can just cut and paste this into my source code. I’m not generating a whole file, I just want the tiny code snippet that will draw the specific thing that I want to draw right now. It is simple, and does this one thing well, and from that perspective, I’d say the app is a success.

But the code… is it good?

Well, the code is decent. It’s generated, so it’s not hand optimized for your use case. You’ll want to edit it when you put it into your source. This is to be expected.

It does not optimize for multiple identical objects, meaning it doesn’t generate loops, or functions, or anything fancy like that whatsoever, it just generates the bare minimum basic Core Graphics drawing code you need to draw whatever it is you um… drew on the canvas.

This might actually present a problem for using this long term since the code you actually use from it will be different from the code it generates (because you will edit it). I’d argue, however, that this is simply an unreasonable expectation. The purpose of this app is to make code snippets that you will use in your app, not to generate your app.

With regard to the code itself, well, again, it’s basic. I was a bit surprised, for example, that the code didn’t seem to use CALayer attributes very much, like for example to draw shadows. This isn’t a huge deal, this is one of those things I’d do, but others might choose differently. There might be some technical reason for the style of code they generated and the API they used, but if there is, I don’t know what it is.

@schwa asked on Twitter:

If the code generated isn’t template based then there’s no fixing of bugs in it.

and the answer is, no, the code is not template based, nor does it appear that there are any preferences that would enable you to modify the code generated. This might be an issue for you if you’re expecting to be regenerating the code from the app and putting it in your app over and over.

I would say that the ability to customize the code output (via templates or preferences) is one of the biggest areas that PaintCode could improve, but it’s not a show stopper for me. I understand the limitations, and would rather have a tool like PaintCode in it’s current form without the code generation customization, than not have it at all.

A side note here is that PaintCode should not be used as a crutch. You need to understand the code it is generating. If you do not, I would actually advise not buying it. Go write some hand crafted Core Graphics code for a year or so, THEN come back and use PaintCode to help make your workflow a little faster and easier.

Can I use it to build my GUI and make it all resolution independent and stuff?

No, I wouldn’t do that. The developers (Pixel Cut) seem to imply that PaintCode will free you from the tyranny of image based GUI design and make your apps resolution independent! (My words, not theirs) This might be true if you designed all your icons and graphics using it, and then generated modules directly into your source folder and were used in your project.

The problem is, because of the lack of customization of the code generation, this kind of app will not be something you will use to regenerate your graphics repeatedly. You’ll use it once, to get a basis for hand optimized CG code, and then you may return later and use it again, but then you’ll need to hand optimize it again. That’s a bit of a pain.

If your requirements are simple, this model works… if you are generating your whole UI this way, it does not.

I would argue that PaintCode stands on it’s own without this capability. Honestly, I don’t think it’s possible to make an app that would generate perfect customizable drawing code even using templates. I think this is an impossible problem to solve, and I kinda hope that Pixel Cut doesn’t try too hard at it. Improve the code generation customization options… sure… but you’re never gonna get it perfect, and you’re never gonna satisfy everyone. When you can do that, we won’t need programmers anymore.

Are it’s graphics tools good? Is it really a painting app?

It’s tools are decent, but not great. Very much a 1.0 feature set. A solid 1.0 feature set, but a 1.0 nonetheless. It does not have layers, or grouping of objects, but it does have bezier curves, rounded rects, and interestingly, the ability to join and split objects, which is something I never would have expected in a 1.0. It has gradients, and shadows and inner shadows and things, all the basic tools… but it won’t replace Photoshop or Illustrator any time soon.

All that said, Opacity has a much wider selection of tools and is clearly a much more graphic tool intensive app, but I’ll be honest… I fired up Opacity, and there was SO MUCH STUFF that I actually didn’t even know where to start. PaintCode, on the other hand, was up and running and was able to generate some basic CG code in minutes.

The interesting dichotomy here is that PaintCode has no help file, no instructions, no preferences, nothing. It’s so simplistic, that my first impression was that it’s simplicity was an indication that it wasn’t worth it’s price. Opacity, on the other hand, has help, and tutorials, and videos, and goodness knows what else. All that and, for me, PaintCode was usable, and Opacity was not.

FWIW: I actually still haven’t figured out how to generate CG code from Opacity. I’m told it’s in there, but I can’t find it.

Can I import or export graphics files?

No, basically, you cannot. It does support exporting PDF or NeXT TIFF files, but as pointed out on Twitter, import/export of svg files would make it a much more useful app. Designers like their existing apps, and if PaintCode wants to play in this space, I think it needs to be better about interoperability. This is definitely a minus.

Interestingly, it might also be fun to be able to paste Core Graphics code into PaintCode and have it draw the result on screen, be able to modify it and have the code change according to the modifications! That would be fun. For now, however, the code panel is read-only.

So, to sum up…

It’s a good app that does one simple thing well, and for that one simple thing, IMO, it’s worth $80, yes.

As Brian Webster pointed out if it saves $80 worth of your hourly wage, then it’s worth it, and for me, I think it will.

I can easily see spending an hour crafting CG code that I could draw up in PaintCode in 5 minutes. Would I return to it later to tweak that code? No. But I’d still have gotten my money’s worth out of it.

Compared to Opacity… well, I wanted to love Opacity… I originally looked at Opacity more than a year ago, for exactly the use case I want PaintCode for. Then, as now, I just couldn’t figure it out. I couldn’t really determine if it’d let me generate the code I wanted, and even if it could… it actually seemed like it would be more effort to design the graphics in Opacity than to just write the Core Graphics code by hand. It seems as if Opacity is a so-so drawing app with the ability to generate Core Graphics code tacked on somewhere.

PaintCode is the opposite. It’s a focused programming aide and a welcome additional tool in my arsenal.

Update

I left off a sample of the code it generates. Here’s the code it generated from the screenshot above.

Update 04/04/2012

They now have a free trial. Go check it out!

Leaking ARC Memory on an NSURLConnection Wrapper?

Wednesday, October 12th, 2011

Wherein I document a case of my ignorance in the hopes you can avoid going down the same rat hole. This is a bit long and rambling, my apologies for that.


As you may know, gentle reader… I have decided to go full steam ahead to converting my apps to ARC.. It’s been a fun process… with it’s own share of complexities, but overall, not too bad. My first converted app, Wasabi, was fairly easy. However, there are a few design patterns I tend to use in my code which skirt the rules of prudence when writing manual retain and release Objective-C, so I was a bit concerned how ARC would handle them. To some, the solutions may be obvious, but they weren’t at all obvious to me, so I’m documenting them here, in case someone else should run into a similar issue. In this case, the issue turned out not to be anything to do with ARC at all, but my tracking it down was educational nonetheless, and useful, I suppose, to talk about.

So, without further ado, I offer you the following manual retain and release Objective-C code:

- (IBAction)buttonPushed:(id)sender 
{
    NSURLRequest *req = [NSURLRequest requestWithURL:
            [NSURL URLWithString:@"http://ax.phobos.apple.com.
                  edgesuite.net/WebObjects/MZStoreServices.woa/
                  wa/wsSearch?term=zen"]];

    JSONWebCommand *command = [[JSONWebCommand alloc] 
                  initWithRequest:req];

    command.completionBlock = ^(NSDictionary *result)
    {
        NSLog(@"Complete. Result: %@", result);
    };

    command.finallyBlock = ^
    { 
        NSLog(@"Finished"); 
        [command release];
    };

    NSLog(@"Starting load...");

    [command start];
}

So, in this code… there’s this JSONWebCommand class, whose purpose is to wrap an NSURLConnection and make it simpler to use and give it some block capabilities. Basically, no need to implement delegate callbacks and things, you just give it blocks instead of a delegate, and it automagically parses the resultant response from JSON to an NSDictionary. Everything is nice and clean. The finallyBlock is always called, regardless of whether the command completes successfully or not. So I used this in the past, as shown here, to release my command ([command release]).

This way I could make this call be very fire and forget. That is, I fire off this command, and I forget about it. I don’t need to hold onto an instance of my command or anything. It’ll call me back when it’s done. It does what I want it to do, and then is released.

ARC converted this code to:

- (IBAction)buttonPushed:(id)sender 
{
    NSURLRequest *req = [NSURLRequest requestWithURL:
            [NSURL URLWithString:@"http://ax.phobos.apple.com.
                  edgesuite.net/WebObjects/MZStoreServices.woa/
                  wa/wsSearch?term=zen"]];

    JSONWebCommand *command = [[JSONWebCommand alloc] 
                  initWithRequest:req];

    command.completionBlock = ^(NSDictionary *result)
    {
        NSLog(@"Complete. Result: %@", result);
    };

    command.finallyBlock = ^
    { 
        NSLog(@"Finished"); 
    };

    NSLog(@"Starting load...");

    [command start];
}

Not much different… but a key issue here… my release is gone!

Of course, that’s exactly what ARC is supposed to do, but WTF! I thought… urm… I’m gonna start it and it’s going to be immediately released! That won’t work!

But it did work. It worked just fine. It appeared all of the cases of this code worked without crash and without issue. How could this be?

Based on my knowledge of what ARC was doing… my command should be deallocated at the end of this method and hence none of the blocks should get called. They were, however, and this was perplexing to me!

I posted a subset of this code on the developer forums, and Greg Parker informed me that if I wanted to get my desired behavior, that is, an object that contains a block which deallocates the object, a good way to do it would be to do:

__block Foo *foo = [[Foo alloc..]];
foo.completionBlock = ^{ foo = nil; };
[foo start];

Essentially specifying an __block modifier for the variable and then setting it to nil in the completion block. Sure enough, this sounded like exactly what I wanted, and is… in other cases than this, probably a perfectly valid pattern to use for this kind of code. Still, I was perplexed that since I had this code sprinkled through my project, why was I not encountering any issues?

Finally, I decided I wanted to track down exactly what the compiler was doing here to educate myself a bit more on how ARC works.

I looked for a tool in Xcode that could give me a listing of where all the retains and releases were being inserted, but I found no joy.

To be clear… since I wasn’t sure what was going on here… I needed to rule out two different issues… First, that the JSONWebCommand wasn’t being over released. If it was, it could ultimately crash my app. Second, that perhaps the JSONWebCommand wasn’t being released. In this case, I might wind up with a leak. The tool to do this in both cases is Instruments.

I knew that the latest version of Leaks is capable now of even detecting leaks that are a result of retain cycles. Retain cycles are among the few cases where ARC might leak memory. This is because one way to get ARC to not release your object is by having it be retained by something that owns it. (i.e.: A owns B which owns A). This is a retain cycle, and ARC does not detect nor prevent it. It’s really easy to make retain cycles using blocks because of the way that blocks capture local variables. For example:

self.foo = [[Foo alloc] ...];
foo.completionBlock = ^{ [self doBar]; };

In this case, foo is owned by self, and the call [self doBar] inside the block also captures self, strongly, within the block. The block is copied by foo, and so any objects captured within it are retained by foo. Since foo is also owned by self, this is a retain cycle. It’s insidious, and not obvious at all when you just look at it. It gets worse too, when you do this:

self.foo = [[Foo alloc] ...];
foo.completionBlock = ^{ [bar doSomething]; };

In this case, bar is a member variable on self. Because it’s a member variable, it still captures self, even though self is not explicitly shown. In other words, this is still a retain cycle.

In the past, we resolved these kinds of retain cycles using techniques that declared a new variable to hold self which is modified with the modifier __block. This is because, in the past, the __block modifier basically made a weak, writable reference on the heap to the variable in question. For example:

__block id blockSelf = self;
foo.completionBlock = ^{ [blockSelf doBar]; }; 

So this would break the retain cycle. Under ARC however, the behavior of __block has been changed! __block variables are now strong, so this will NOT solve your retain cycle! Instead, you should now use the following pattern, which takes advantage of the __weak modifier.

__weak id blockSelf = self;
foo.completionBlock = ^
{
    id strongSelf = blockSelf;
    if(strongSelf)
        [strongSelf doBar];
};

This is the safest way to go, since blockSelf is a zeroing weak reference… when the block executes, if self has been deallocated, then your code won’t crash. Now, if you’re on iOS 4, or Mac OS 10.6, then you don’t have __weak… so instead, you can still get the same behavior that you had before by using __unsafe_unretained in conjunction with __block:

__block __unsafe_unretained id blockSelf = self;
foo.completionBlock = ^{ [blockSelf doBar]; }; 

Just realize that if self gets deallocated your app might blow up. Coder beware!

But anyway… I have digressed… none of this was what was happening in my code. Instruments showed no leaks… and in fact, I could see (by creating a dealloc method on my JSONWebCommand and putting a breakpoint in it) that my command was being deallocated. The only question was if it was being deallocated before I was done with it or not. I then ran the NSZombies instrument on the code… and it showed that it was not being prematurely deallocated. So that left me with the question of… How in the heck is ARC knowing the right thing to do here? So finally, I decided to do some hardcore code spelunking…

I asked around a bit on Twitter, and Stefen Lasser suggested that I use the Xcode debugger to set breakpoints on the ARC runtime methods themselves. You can do this yourself by setting symbolic breakpoints on objc_retain objc_release etc… This can be very noisy, however, so you’ll either want to disable them initially until you hit a specific point in your program, or tweak the conditions on the breakpoint to only break on certain classes. For example, you could set a conditional symbolic breakpoint on objc_retain such that it only fires when it’s parameter is of type JSONWebCommand (this may require some console gdb-fu).

In the end, this is exactly what I did… I basically ran my program up until my block of code… then set my breakpoints on the release/retain methods… and looked up the stack as each was called in turn… and here’s what I found:

This code…

connection = [[NSURLConnection alloc] 
 initWithRequest:request delegate:self startImmediately:NO];

is inside JSONWebCommand… can you spot it? Well it turns out… NSURLConnection retains it’s delegate! I’d gotten so used to delegates that are not retained, I had looked at this code a dozen times and thought “No, that can’t be retaining me… that’s a delegate!” But I traced it up to there, and saw the retain, and I said “What? How can that be retaining self?” I checked the documentation and… sure ’nuff… that’s the way that bugger works. It retains it when set, and releases it when the connection terminates.

So I guess in the end… what did I learn?

Well, I got some practice using the new tools in Instruments. Check them out… they’re excellent! In particular watch the WWDC videos on Instruments. Good stuff.

I also learned a bit about how to trace around inside ARC’s inserted code. Truth be known, I didn’t actually need the release in my block at all even before changing to ARC. So the tool was smarter than me! Less code is always better! I guess the key takeaway here, however, was that ARC wasn’t doing anything surprising. It was doing exactly what it should have done! I would have been far more bothered if it turned out it had some kind of magic it was working. But it wasn’t.

Creating Adapters Using Protocols

Saturday, July 30th, 2011

I have some code I’ll be open sourcing in the next month or so. It uses a third party JSON library to convert Objective-C objects to JSON objects. When I wrote it, the most popular JSON library out there was TouchJSON. Today, although TouchJSON is certainly still popular, there are many other JSON parsing libraries available.

That said, in general, I’d say it’s poor form to require third party libraries when distributing an open source component. It’s difficult enough for people to integrate your code into their projects, let alone bringing in even more code from other libraries. Furthermore, what if the consumer of your component already has chosen a library that does what you need the third party library to do and doesn’t want to add yours?

Decoupling Is Good For You

The root of this problem has to do with coupling. When your code is coupled closely to specific libraries or other classes that you do not provide as part of your distribution, it decreases its reusability.

Because of these issues, I’d prefer not to distribute this code if it’s going to force users to be locked in to using TouchJSON.

Fortunately, Objective-C provides us with some awesome tools to help reduce coupling. The tool I’d like to talk about today is protocols and how you can use protocols to decouple your code from specific frameworks by using it to implement the Adapter pattern.

Even though TouchJSON has various methods for encoding objects to JSON from NSDictionary, NSArray, and other foundation container classes, remember that we don’t want to couple ourselves to TouchJSON. We want to make it possible to use our code with any JSON encoding library. So what we need is to tell users of our code exactly what we need from a JSON library so that they can implement adapters for whatever library they want to use.

This is a perfect case for using protocols.

A protocol allows us to define an interface that other objects can implement. We can then write our code according to the protocol and not the specific interface of the library. This way, users of our code can pass in any object that conforms to the protocol – including our adapter.

Let’s look at some code!

First, to define an protocol, you define it using the @protocol directive.

@protocol MyDoodadProtocol
-(NSString *)encodeDictionary:(NSDictionary *)inDictionary;
@end

As you can see, here we’re defining the MyDoodadProtocol protocol. In it, we’ve defined just one method, -encodeDictionary:. This method is our adapter method for talking to whatever JSON encoding framework we’re using. The implementation of this method is left up to our adapter later.

To use the MyDoodadProtocol protocol, we simply need to pass an object into our MyDoodad which conforms to it. We check this when it’s passed in by declaring that the type of the object is id<MyDoodadProtocol>. This limits the type of argument to an object conforming to the protocol. If we pass something else, it’ll generate a compiler error

@interface MyDoodad : NSObject
{
    id<MyDoodadProtocol> encoder;
}
-(id)initWithJSONEncoder:(id<MyDoodadProtocol>)inEncoder;
-(void)doStuffWithDictionary:(NSDictionary *)inDictionary;
@end

@implementation MyDoodad
-(id)initWithJSONEncoder:(id<MyDoodadProtocol>)inEncoder;
{
    if((self = [super init]))
    {
        encoder = [inEncoder retain];
    }
    return self;
}

-(void)doStuffWithDictionary:(NSDictionary *)inDictionary
{
    // we already know it implements our protocol, 
    // so we can use it here
    // if we didn't know, though, 
    // we could check respondsToSelector or 
    // conformsToProtocol here as well.
    NSString *json = [encoder encodeDictionary:inDictionary];   

    [self doSomethingWithJSON:json]; // ....
}

@end

The actual implementation of the adapter can be as simple as a class which acts as an intermediary. This one uses TouchJSON…

@interface MyDoodadAdapter : NSObject <MyDoodadProtocol>
-(NSString *)encodeDictionary:(NSDictionary *)inDictionary;
@end

@implementation MyDoodadAdapter
-(NSString *)encodeDictionary:(NSDictionary *)inDictionary;
{
    // TouchJSON uses "serializeObject"...
    NSData *data = [[CJSONSerializer serializer] 
                serializeObject:inDictionary error:nil];
    NSString *ret = [[NSString alloc] initWithData:data 
                encoding:NSUTF8StringEncoding];
    return [ret autorelease];
}   
@end

So by doing this, your code is only having to rely on the protocol, and not on the specific implementation of any given library. Users of your code can pass any object they want into the initializer, and your code will use just the interface it’s declared it needs via the protocol. It’s a nice clean way to decouple your code from dependencies.

Why not use inheritance?

Using a protocol is better than using a class and requiring the user inherit from your class because you never know what kind of class hierarchy your user may already be using. She may want to make the adapter from a class that’s already inheriting from something else, or even simply make a category on the encoding library itself. For example:

@interface CJSONSerializer (MyDoodadAdapter) <MyDoodadProtocol>

-(NSString *)encodeDictionary:(NSDictionary *)inDictionary
{
    NSData *data = [self serializeObject:inDictionary 
        error:nil];
    NSString *ret = [[NSString alloc] initWithData:data 
        encoding:NSUTF8StringEncoding];
    return [ret autorelease];        
}

@end

This code actually extends the TouchJSON API directly, and adds the required method directly to the CJSONSerializer class. This can be very convenient and keep us from having to add additional classes to our code. As shown here, categories can be declared to conform to protocols just like classes can.

Is this something I should do all the time?

In a nutshell… no. If you’re using a lot of capabilities from a library, making adapter protocols for everything in the library is impractical and would be a very bad idea. However, if you only need a few methods, providing the ability for users of your code to use an adapter instead of having to be locked into the library you used originally is a great way to provide additional flexibility and make it much easier to integrate your code into their projects. So like all things, use it in moderation and it can be a great tool!