15

I have a lot question marks tolling above my head. What I don't get is before xcode 4.3 I needed to declare forward declarations (for private methods) in my implementation file.

Like in my .m file:

// deleting this with xcode 4.3 the below code still does work 
// in previous versions i had to put this because otherwise the compiler can't find methodFirst
@interface DetailViewController ()
- (void)methodFirst;
- (void)methodSecond;
@end


@implementation DetailViewController

- (void) methodSecond
{
   // if i delete the forward declaration now adays i dont get a compiler error that he cant find method first
   [self methodFirst];
}

- (void) methodFirst
{
}

@end

Now it seems I don't need to do that anymore? Did Apple update the compiler so that it isn't needed anymore to put forward declarations?

I can't find any reference to an official Apple source about this change. I wonder what other people have encountered in their new environment.

JonasCz
  • 11,174
  • 6
  • 40
  • 61
test
  • 323
  • 1
  • 3
  • 9
  • What do you mean by declaring private methods? Can you post an example? As far as I know, Objective C doesn't support private methods. – sch Feb 23 '12 at 13:57
  • sry my bad its more a forward declaration in my .m file but it seems that it isn't needed to make forward declarations? – test Feb 23 '12 at 13:59
  • the above code works, when i delete the @interface part it still works but then i expect xcode to give me a warning from the compiler because he can't find methodFirst. but strangely it doesn't do that :s – test Feb 23 '12 at 14:21
  • See also: this answer (http://stackoverflow.com/a/9984097/774) to a similar question. – cbowns May 03 '12 at 01:51

2 Answers2

34

As of the LLVM Compiler version shipped with Xcode 4.3, if you try to call a method that the compiler has not previously seen, it will look in the rest of the current @implementation block to see if that method has been declared later. If so, then it uses that, and you don't get a warning. Hence, as of Xcode 4.3, there's much less need to pre-declare your internal methods. Clearly, you still need to declare methods that are publicly exposed to other classes.

This change was noted in the release notes of some of the Xcode 4.3 betas, but apparently didn't make it into the "What's New in Xcode 4.3" final documentation.

Unlike has been suggested in other answers, this is not just an "Undeclared Selector" warning that has been turned off by default. In fact, if you're using ARC, unrecognized selectors are still hard errors. Try calling [self myNonexistentMethod] and you'll see; the compiler still complains.

BJ Homer
  • 47,750
  • 10
  • 111
  • 128
  • 1
    thanks so no need anymore for 'private method' forward declaration? yay! :) strange that it didn't made it in the final release notes :\ – test Feb 23 '12 at 16:56
  • One reason to continue to declare class extension ("private") methods: for wiring up IBActions using Interface Builder. As of Xcode 4.5.2, IB will not acknowledge IBActions if they are only implemented but not declared. – Jeff Dec 02 '12 at 21:03
  • Great answer! So in your opinion should we forward declare private methods, not forward declare, or is it just arbitrary at this point and best to go with whichever pattern your team feels more comfortable with. – Kyle Clegg Nov 23 '13 at 10:19
  • @Kyle I see no reason to forward-declare in the general case. In fact, I prefer not to, as it clutters up the method picker list in the jump bar. There may be some reasons to do so (e.g. documentation of a group of related methods), but usually, I just avoid it. – BJ Homer Nov 23 '13 at 19:55
5

There aren't any private methods in Objective-C. What you're thinking of is the class continuation, the "nameless" category interface you can declare in your .m file to declare methods that will be in the class implementation, but that aren't in the public interface.

There's never been a requirement to declare methods before they're used. However, it's always been a good idea, and the compiler has a warning flag to indicate when methods that haven't been seen are used. The reason is to do with the operating system's calling convention for functions. Different types, such as structures, floating point numbers, integer numbers, and pointers, can all be handled in different ways when they are the arguments to or return values from functions. Indeed, on different computers and in different operating systems, they are handled in different ways. To know how to handle the arguments and return values for an Objective-C method, the compiler needs to know the signature for that method: how many arguments of what types it takes, and what type it returns.

If it hasn't seen a declaration of the method, then the compiler will need to make a guess. If that guess is incorrect, then it can end up putting the wrong values into the arguments, or interpreting the return value incorrectly, or trying to take something off the stack that doesn't exist.

  • Does that mean that in xcode 4.3 the compiler warning has been supressed? i could almost know that in the previous version i got a compiler warning but in the latest i don't have it anymore. – test Feb 23 '12 at 14:13
  • It looks like the default value is off in 4.3. The warning you need to enable is "Undeclared selector". –  Feb 23 '12 at 14:21
  • 4
    Wrong. This is not just a compiler warning being turned off. As of the LLVM version in Xcode 4.3, the compiler can look throughout all of the current file to find method declarations. It doesn't necessarily need to be declared earlier in the file anymore. – BJ Homer Feb 23 '12 at 15:20
  • @BJHomer: so where I said it's not a requirement, you say that's wrong because it's not required? Interesting. –  Feb 23 '12 at 15:28
  • @GrahamLee my "Wrong" was in reference to your assertion that the warning was off by default, not the main body of your answer. Sorry if that was unclear. – BJ Homer Feb 23 '12 at 15:34
  • Actually the warning is off by default. I checked. –  Feb 23 '12 at 15:36
  • @GrahamLee Ah. So, you're right that it's off by default. But the "Undeclared Selector" warning only has to do with `@selector(foobar)` constructs. Even with that warning off, it still warns about `[self foobar]`, so that warning is unrelated to the original question. – BJ Homer Feb 23 '12 at 16:48
  • sry for my late response i could finally test it but sadly still i don't get any warnings for that i didn't forward declared my methods. @BJHomer i think that you might be right but aim confused that this is not made officially noted but maybe i overlooked it? :) – test Feb 23 '12 at 16:54
  • Does anyone know how to enforce method declarations in xcode 4.3.1? Its probably a build setting somewhere. In essence I'd like to turn this feature off as others on my team can't compile using 4.2. – Tylerc230 Mar 12 '12 at 17:40