I just started reading my first Objective-C book and it's mostly pretty clear, however I want to understand why it teaches me to declare a method in the interface first, I've tried deleting it from the interface and just doing it in the implementation section and all seems to work so my question is does it matter and if so, what does this help to accomplish?
3 Answers
It's C. Declaring functions/methods in a header allows other compilation units to see your function prototypes and compile based on them. Objective-C works via dynamic dispatch though, so even if you don't declare a method in the header, it still exists at runtime. When you call a method, it is resolved at runtime, so it doesn't matter if it was in the header or not.
The only issue is, if you don't include the method in the header, the compiler has to make assumptions about the return and argument types. It defaults to id, which is 4 or 8 bytes depending on your architecture, and therefore you will get into trouble if the actual return type is of a different size (e.g. structs or BOOL etc).
7 Comments
id on your platform. In that case, the wrong version of objc_msgSend will be used. Instead of using objc_msgSend_stret which is for structs, it will use plain-old objc_msgSend, and you will lose anything past the size of idObjective-C is a highly dynamic language (and runtime) that defers the decision-making to as late as possible.
The code runs fine because at runtime the object does actually respond to the selector you've specified.
By declaring methods, however, you can help the Objective-C compiler to provide you with help in checking that you won't encounter any unexpected situations at runtime.
For example, take the following class:
@interface MDFoo : NSObject
- (void)blah;
@end
@implementation MDFoo
- (void)blah {
NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
- (void)boo {
NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
@end
Let's say that in another controller class, you create an instance of MDFoo and want to send it some messages.
MDFoo *foo = [[MDFoo alloc] init];
[foo blah];
[foo boo]; // compiler warning
[foo yell]; // compiler warning
When you compile the program, the compiler should give you a warning that both of the last two methods can't be found and that an instance of MDFoo may not respond to those selectors.
If you then run the program, the following is what's logged:
foo[10540:303] [MDFoo blah]
foo[10540:303] [MDFoo boo]
foo[10540:303] -[MDFoo yell]: unrecognized selector sent to instance 0x1001082f0
foo[10540:303] *** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[MDFoo yell]:
unrecognized selector sent to instance 0x1001082f0'
So at runtime the warning about boo turned out to be nothing, but the warning about yell was correct and caused the application to terminate.
From a design standpoint, it's also how you let other objects know what messages can be called. (See Objective-C Programming Language: Defining a Class - The Role of the Interface).