Friday, February 19, 2010

MYNetwork

MYNetwork is a handy networking library for iPhone and Mac OS X which abstracts all the socket-level drek and lets you focus on sending and receiving messages.

Monday, January 4, 2010

Network Reachability

Here's a free, BSD-licensed codebase for testing reachability on the iPhone. Also see the UIDevice extension.

Sunday, November 8, 2009

Creating an instance of a class from a string

If you need to create an instance of an Objective C class from a string indicating the class' name:


if (NSClassFromString(className) != nil) {
id theInstance = [[NSClassFromString(className) alloc] init] autorelease];
}

Monday, August 10, 2009

Easy Notifications with #define

When developing an application, I make liberal use of the NSNotificationCenter. It's a handy way to set up events and respond to them.

Unfortunately, the code you need to write to use it is a little long, and is difficult to read. Case in point, say you want to send a message saying "two coins have been inserted". Here's what it would look like:

[[NSNotificationCenter defaultCenter] postNotificationName:@"insertCoin" object:nil userInfo: [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:2] forKey:@"number"]]

Blah. Wouldn't you rather type or read something like this?

broadcastInt( @"insertCoin", @"number", 2);

Well, now you can! (...if you typically only use the defaultCenter and use an object filter of nil, which I do.)

Just add these macros to your prefix file:

// Listening
#define listenFor(__MSG__,__SEL__) [[NSNotificationCenter defaultCenter] addObserver:self selector:__SEL__ name:__MSG__ object:nil]
#define unlistenFor(__MSG__) [[NSNotificationCenter defaultCenter] removeObserver:self name:__MSG__ object:nil]
#define unlisten() [[NSNotificationCenter defaultCenter] removeObserver:self]

// Broadcasting
#define broadcast(__MSG__) [[NSNotificationCenter defaultCenter] postNotificationName:__MSG__ object:nil]
#define broadcastDictionary(__MSG__,__DICT__) [[NSNotificationCenter defaultCenter] postNotificationName:__MSG__ object:nil userInfo:__DICT__]
#define broadcastObject(__MSG__,__KEY__,__VALUE__) [[NSNotificationCenter defaultCenter] postNotificationName:__MSG__ object:nil userInfo: [NSDictionary dictionaryWithObject:__VALUE__ forKey:__KEY__]]
#define broadcastInt(__MSG__,__KEY__,__VALUE__) [[NSNotificationCenter defaultCenter] postNotificationName:__MSG__ object:nil userInfo: [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:__VALUE__] forKey:__KEY__]]


Here's a detailed guide to what the above defines buy you.

listenFor( message, selector )
listenFor( @"somethingHappened", @selector(itHappened:) );
Starts listening for the given message. When the message is received, it calls the given selector in self.

unlistenFor( message )
unlistenFor( @"somethingHappened" );
Stop listening for the given message.

unlisten()
unlisten();
Stops listening for messages altogether. You'll probably want to put this in your dealloc() method.

broadcast( message )
broadcast( @"finished" );
Sends out a notification with the given message. No other data is passed along.

broadcastDictionary( message, dictionary )
broadcastDictionary( @"finished", myDictionaryObject );
If you need to supply arbitrary data to the receiver, you can package it up into a dictionary object, and pass it along.

broadcastObject( message, key, value )
broadcastObject( @"newPerson", @"name", @"Franklin" );
If you only need to send one object with the notification, this handy shorthand saves you the trouble of creating the NSDictionary object. It creates the dictionary for you, with the single key-value pair given.

broadcastInt( message, key, value )
broadcastInt( @"newPerson", @"age", 12 );
If you need to send an integer, which I find I often do, this shortcut also creates the NSNumber object to put in the dictionary for you.

Thursday, February 5, 2009

CALayer leaks from UIButton

I don't know why, but I was leaking CALayer objects when I used the code:

UIButton *button = [[UIButton buttonWithType:UIButtonTypeCustom] initWithframe: myCGRect];

I solved this by replacing the above code with this:

UIButton *button = [[[UIButton alloc] initWithFrame:myCGRect] autorelease];

If you know why this is, I'd love to hear about it.

[iPhoneDevelopersGuide description];

This is the iPhone Developer's Guide, the companion to the Shockwave3D Developer's Guide, only for iPhone programming instead of Director programming. In essence, it's the site I wish I found when I started iPhone development, where I collect the solutions to the things that confused me, and which I figured out later.

Full disclosure: I'm learning this stuff as I go. If some Cocoa guru tells you I'm full of it, he's probably right. In that case, please let me know where I'm going astray.