我关于 stackoverflow 的第一个问题,所以请保持温和。我尝试寻找答案,但我真的需要这方面的帮助。
问题在于从 Neal Goldstein 的 Objective-C for Dummies 中学习委托(delegate)
他在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
--
//然后在 Transaction.m 他有这个
#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
我无法理解 Transaction.m 文件中的花费方法
id 类型实例变量可以调用包含它的类中的任何方法吗? 我知道 respondsToSelector 是一个 NSObject 方法,它告诉编译器是否已经实现了一个方法。但是,id 类型的委托(delegate)如何调用该方法呢?编译器甚至不知道它是什么对象...
请帮忙!
附言如果有人对优秀的 Objective-C 书籍有任何推荐,我将不胜感激。我想进入 iPhone 开发,但我认为我需要先很好地掌握 Objective-C 的基础知识。
谢谢!
最佳答案
是的,您可以向delegate
变量发送任何消息,因为它的类型是id
。
你写了这个:
[delegate spend:self];
编译器将其转换为对 objc_msgSend
函数的调用,如下所示:
objc_msgSend(delegate, @selector(spend:), self);
在运行时,objc_msgSend
函数在delegate
的类(及其父类(super class))的方法表中搜索与选择器 spend:
.
顺便说一句,我们通常这样声明delegate
变量:
id<TransactionDelegate> delegate;
这会通知编译器delegate
将是一个符合TransactionDelegate
协议(protocol)的对象。当您尝试向 delegate
发送消息时,此声明将帮助 Xcode 为您提供更好的自动完成功能。如果您以这种方式声明您的 delegate
setter 方法或属性,编译器还会在编译时检查您是否将其设置为符合协议(protocol)的对象。
关于objective-c - id 类型实例变量向实例方法发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15345411/