A few of my friends have recently asked me how to share code between their applications. Here's a screencast walking you through how I solve this problem. It works really well for me. I hope this is useful to you.
You can get my terminal shortcuts from my dot files repo on GitHub. You can also find the test app and test library on GitHub.
The git submodule documentation might also be useful to you if you're new to working with submodules. If that's a little hard to understand (I know it is for me), just try googling it. There's a lot of good resources on submodules.
For the seasoned Cocoa developer, this is a piece of cake. For newer developers, this can be a real pain, especially if you don't know what you're looking for. I get this question a decent amount, so I figured I'd put a quick guide together.
The Problem
You can't put just any object in a plist. This mainly gets people when they want to put something into NSUserDefaults and get an error (because NSUserDefaults archives to a plist under the hood).
Plists only support the core types: NSString, NSNumber, NSDate, NSData, NSArray, NSDictionary (and their CF buddies thanks to the toll-free bridge). The key here is NSData. You can convert any object to NSData with the NSCoding protocol.
The Solution
There are two things you have to do: implement NSCoding and then use the archiver and unarchiver.
Implementing NSCoding
Say you have an object that looks like this:
@interface Note : NSObject {
NSString *title;
NSString *author;
BOOL published;
}
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *author;
@property (nonatomic) BOOL published;
@end
#import "Note.h"
@implementation Note
@synthesize title;
@synthesize author;
@synthesize published;
- (void)dealloc {
[title release];
[author release];
[super dealloc];
}
@end
Pretty simple, right?
Now, all you have to do to implement NSCoding is the following:
@interface Note : NSObject <NSCoding> {
NSString *title;
NSString *author;
BOOL published;
}
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *author;
@property (nonatomic) BOOL published;
@end
#import "Note.h"
@implementation Note
@synthesize title;
@synthesize author;
@synthesize published;
- (void)dealloc {
[title release];
[author release];
[super dealloc];
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
self.title = [decoder decodeObjectForKey:@"title"];
self.author = [decoder decodeObjectForKey:@"author"];
self.published = [decoder decodeBoolForKey:@"published"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:title forKey:@"time"];
[encoder encodeObject:author forKey:@"author"];
[encoder encodeBool:published forKey:@"published"];
}
@end
Pretty simple. All I did was add the <NSCoding> protocol delectation in the header file and initWithCoder: and encodeWithCoder: in the implementation. You use these methods to tell NSCoder how to encode your object into data. Notice how two of the variables are objects and one was a BOOL. You have to use different methods for non-objects. The NSCoder documentation has the full list.
Remember, that you can use NSCoder to archive your object however whatever you want. It doesn't have to just be all of the instance variables in your object, although that's what you'll do 90% of the time.
Using the Archiver and Unarchiver
This part is also really easy. Let's say you have an array of notes that you want to put into NSUserDefaults, here's the code:
// Given `notes` contains an array of Note objects
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:notes];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"notes"];
Unarchiving is just as easy:
NSData *notesData = [[NSUserDefaults standardUserDefaults] objectForKey:@"notes"];
NSArray *notes = [NSKeyedUnarchiver unarchiveObjectWithData:notesData];
A lot of people ask me how to learn Ruby on Rails. I usually forward this email I wrote awhile back to a friend. I figured it would probably be better to post it on my blog so more people can benefit from it.
Here's the email:
Hey man,
Rails is awesome. If you're not familiar with Ruby, I'd recommend getting acquainted with it first. I spend 2 hours reading a PDF online and then jumped in. The more you understand Ruby, the less magical Rails seems. The Ruby Programming Language is a great book. Matz (the creator of Ruby) is one of the authors. A lot of it is like "this is they way it is because when I designed it I though this". I liked it a lot.
The Poignant Guide is another really popular way to learn Ruby. There's a bit of history to it, but nevermind that for now.
Once you feel semi comfortable with Ruby (i.e. you can make a class that has methods, inheritance, control structures, etc), watch this 15 minute video. It will blow your mind. My next step was going back through it and trying to build it myself. This was really hard at first cause I had no idea what I was doing and didn't understand the syntax yet. Don't worry.
Try to write something simple in Rails. Maybe a blog or to do manager, etc. I learn by doing. This was the best for me. I've rewritten my blog at least 20 times. (By the way, it's open source on GitHub.)
The best resource I've found is Railscasts.com. They are really well done. Pretty much anything you could want to do, he has already covered. After I got several under my belt, I sorta "got it" and started really understanding what I was writing. #carlhuda on freenode (IRC channel) was also super helpful. @wycats (he's on the core team of Rails and jQuery) is in there and he's really great about helping new comers and teaching you stuff.
Ruby5 is also really great. It's a biweekly 5 minute podcast about news in the Ruby and Rails community. I've found lots of great stuff there.
Let me know if you need any help or have questions. I'd be happy to help.
Sam
More Stuff
I have several open source projects on my GitHub profile. My blog and Markdownr.com are two fairly straight forward Rails 3 projects.
I highly recommend learning Git. The Git documentation page will help a lot if you're trying to learn.