views:

128

answers:

1

In Apple's The Objective-C Programming Language: Defining a Class the section named "Redefining self" recommends that that class methods allocate and return instances use 'self' only to allocate an instance and then refer only to that instance. Thus, I have a number of subclasses, that have class methods along the lines of:

+ (id)scrollViewWithFrame: (NSRect)rectFrame
{
    id newInstance = [[[self alloc] initWithFrame:rectFrame] autorelease];
    [newInstance setHasHorizontalScroller: YES];
    [newInstance setHasVerticalScroller: YES];
    [newInstance setBorderType: NSNoBorder];
    [newInstance setAutoresizingMask: (NSViewWidthSizable
                | NSViewHeightSizable)];

    return newInstance;
}

The above is, of course, a subclass of NSScrollView. Unfortunately, with Xcode 3.x all these NSView subclasses now raise warnings: "Warning: Multiple methods named '-setAutoresizingMask' found". I believe it has something to do with GCC 4.2, which uses the Xcode default settings.

The warning is correct, of course, since NSView and its various subclasses all implement setAutoresizingMask, but it is also unnecessary. Since they're only warnings, I ignore them but there is a risk that in between the thirty or so unnecessary ones, a really useful warning lurks which I simply don't see. So, what to do? I do want to adhere to good coding practices and I want to build warning-free apps -- how can I do both?

+3  A: 

That warning about "multiple methods found" means that more than one class implements setAutoresizingMask: and the compiler can't tell which one this is because the variable is typed id. The compiler is warning you that it's possible (since the class of the object is unknown) that you might get the wrong one. Try typing newInstance either as an NSScrollView* or as your class and the warning will go away. You can still return id, since it's equivalent to all object-pointer types. It's just the variable you're sending messages to that the compiler wants to be statically typed.

Chuck
Good answer. I'd cast it to the subclass, because this method is going to be implemented by the subclass, and all subclasses below it.
bobDevil
I would too, but it doesn't make much of a difference in that implementation, since we're only calling NSScrollView methods.
Chuck
Unfortunately, Chuck's answer raises two new questions for me: 1) Why does Apple write "id newInstance = [[self alloc] init]; // EXCELLENT" in their documentation and not "Rectangle *newInstance = [[self alloc] init];".2) Why does a quick search on "newInstance lang:objectivec" on Google code show that 99% of the results favor "id newInstance" ?I don't have the knowledge to answer these questions, but I'm a bit wary of quick fixes.
Elise van Looij
@Elise van Looij: Probably because most people do not run into this warning and most of the rest are unconcerned by it. As I said, this is just how you stop that warning from appearing — aside from shutting the compiler up in this particular case, it's totally optional. Only if it said multiple method *signatures* were found would static typing become necessary to ensure correct code.
Chuck
But Chuck, it's only when multiple signatures are found that this warning is even thrown! It doesn't even progress to an error until the compiler picks one method, you call the other one, and the compiler finds it can't convert the argument or return value.
codewarrior
So Chuck gets the green V, but @bobDevil is right -- if you do this, always type the newInstance to the subclass, unless you enjoy getting 'Unknown method' errors on your new instance. Or wondering why your overrides aren't working.
Elise van Looij