my first question on stackoverflow so please be gentle. I've tried searching for answers but I really need help with this.
The issue is with learning about delegates from Neal Goldstein's Objective-C for Dummies
He has the following in Transaction.h
#import <Cocoa/Cocoa.h>
@class Budget;
@interface Transaction : NSObject {
Budget *budget;
double amount;
NSString *name;
id delegate;
}
//some init method
@end
@protocol TransactionDelegate
@required
- (void) spend: (Transaction *) aTransaction;
//additional optional method
@end
--
//and then in Transaction.m he has this
#import "Transaction.h"
#import "Budget.h"
@implementation Transaction
@synthesize budget, delegate , amount;
- (void) spend {
if ([delegate respondsToSelector:@selector(spend:)])
[delegate spend:self];
}
- (id) initWithAmount: (double) theAmount forBudget: (Budget*) aBudget {
if (self = [super init]) {
budget = aBudget;
[budget retain];
amount = theAmount;
}
return self;
}
- (void) dealloc {
[budget release];
[super dealloc];
}
@end
I have problem understanding the spend method in the Transaction.m file
Can the id type instance variable call ANY method in the class that contains it? I understand that respondsToSelector is a NSObject method that tells the compiler if a method has been implemented. But how can delegate which is of id-type call that method? the compiler does not even know what object it is yet...
Please help!
P.S. if anybody has any recommendations on good Objective-C books, I'd highly appreciate it. I wanna get into iPhone development but I figured I need to get a good grasp on the basics of Objective-C first.
Thanks!
Yes, you can send any message to the delegate variable, because its type is id.
You wrote this:
[delegate spend:self];
The compiler turns that into a call to the objc_msgSend function, like this:
objc_msgSend(delegate, @selector(spend:), self);
At runtime, the objc_msgSend function searches the method table of delegate's class (and its superclasses) for a method associated with the selector spend:.
Incidentally, we usually declare the delegate variable like this:
id<TransactionDelegate> delegate;
This informs the compiler that delegate will be an object that conforms to the TransactionDelegate protocol. This declaration will help Xcode give you better autocompletion when you're trying to send a message to delegate. If you declare your delegate setter method or property this way, the compiler will also check at compile time that you're setting it to an object that conforms to the protocol.
Good question. Gets at one of the key differences between Obj-C and other compiled languages.
You may send any message to any Objective-C object you like. The message send will try to be resolved by the library called the runtime library and this happens at runtime. At compile time, if you have an object type other than the generic id some IDEs may flag it as a likely user mistake.
At runtime, the runtime library will look for a matching method and then would look whether the class has a fallback handler that wants it and as a last resort would throw an exception. The user code could very well catch this exception and treat it as a normal situation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With