Multiple classes; same init selector with different argument types

Discussion in 'Mac Programming' started by Thomas Harte, Aug 5, 2010.

  1. Thomas Harte macrumors 6502

    Nov 30, 2005
    Apologies for the brief title. I have a whole bunch of classes that are more or less of the form:

    @class ThisClass;
    @protocol ThisClassDelegate
    - (void)thisClassDidSomething:(ThisClass *)instance;
    - (void)thisClassDidSomethingElse:(ThisClass *)instance;
    /* etc */
    /* some more things */
    @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:

    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:

    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?
  2. lee1210 macrumors 68040


    Jan 10, 2005
    Dallas, TX
    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:
    +(SomeClass *)someClassWithUrl:andDelegate:
    I'm not 100% sure if this will help with your problem, but i thought i'd toss it out there.


    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.
  3. chown33 macrumors 604

    Aug 9, 2009
    descending into the Maelström
    You could embed the class name in the method name, e.g.:

    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.

    The red-hilited code is almost begging for a macro.

Share This Page