Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Thomas Harte

macrumors 6502
Original poster
Apologies for the brief title. I have a whole bunch of classes that are more or less of the form:

Code:
@class ThisClass;

@protocol ThisClassDelegate
- (void)thisClassDidSomething:(ThisClass *)instance;
- (void)thisClassDidSomethingElse:(ThisClass *)instance;
/* etc */
@optional
/* some more things */
@end

@interface ThisClass
{
	/* whatever */
	NSObject <ThisClassDelegate> *delegate;
}

- (id)initWithURL:(NSURL *)url delegate:(NSObject <ThisClassDelegate> *)delegate;

Some of the delegate methods are optional; it is therefore necessary that the delegate be explicitly a subclass of NSObject rather than merely an id since respondsToSelector will be called on it.

This is all fine, except that once I have more than one class which uses the selector initWithURL:delegate:, the following is prone to cause compiler and analyser warnings for one or the other:

Code:
SomeClass *class = [[SomeClass alloc] initWithURL:something delegate:this];

The reason being that 'alloc' returns type id so the type isn't known for the purposes of checking the selector. So I get a warning that 'this' doesn't implement the correct protocol when the compiler checks with one of the various declarations of initWithURL:delegate: that requests an NSObject that implements a different protocol.

It's slightly unwieldy, but I can fix that with:

Code:
SomeClass *class = [(SomeClass *)[SomeClass alloc] initWithURL:something delegate:this];

And still get the warning I want to get if I've forgotten to implement the necessary protocol on the class that I'm nominating as a delegate. I guess I could also supply '+ (SomeClass *)alloc;' that called super alloc then casted the pointer and returned it.

So, I know what causes the problem and I know some slightly displeasing ways to eliminate it. My real question is that, given that a lot of Objective-C is idioms and patterns, am I offending any of the normal conventions? I get a bit anxious any time that things don't end up being neat. Is someone with greater experience able to critique what I'm doing?
 
I'm really not too well-versed with a lot of what you're working with, but I can offer one suggestion:
Factory methods return a concrete type (or can). You could have:
Code:
+(SomeClass *)someClassWithUrl:andDelegate:

I'm not 100% sure if this will help with your problem, but i thought i'd toss it out there.

-Lee

EDIT: Hrm. A quick review of the docs seems to indicate that, at least in Apple's classes, factory methods also return id. I don't know if this is an important convention to follow in your own code, but if so this advice is obviously no good.

EDIT 2: It seems like the id return type for factory methods is for ease of subclassing, etc. If you have no intention to subclass SomeObject, a concrete return type is probably OK.
 
You could embed the class name in the method name, e.g.:
initThisClassWithURL:delegate:

You've already done precisely this with your delegate methods:
- (void)thisClassDidSomething🙁ThisClass *)instance;
- (void)thisClassDidSomethingElse🙁ThisClass *)instance;

So do the same thing with your init methods.


Code:
SomeClass *class = [[COLOR="Red"](SomeClass *)[SomeClass alloc][/COLOR] initWithURL:something delegate:this];
The red-hilited code is almost begging for a macro.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.