2013-03-11 78 views
3

我的第一個問題在stackoverflow所以請溫柔。我試過尋找答案,但我真的需要幫助。id類型實例變量發送消息到實例方法

的問題是與學習有關的尼爾·戈爾茨坦的Objective-C代表傻瓜

他有在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 

我有問題了解花m Transaction.m文件中的方法

id類型實例變量是否可以在包含它的類中調用ANY方法? 我明白,respondsToSelector是一個NSObject方法,告訴編譯器一個方法是否已經實現。但是,如何委託id-type調用該方法?編譯器甚至不知道它是什麼對象...

請幫忙!

P.S.如果任何人對良好的Objective-C書籍有任何建議,我將非常感激。我想進入iPhone開發領域,但我想我需要先掌握Objective-C的基礎知識。

謝謝!

回答

2

是的,你可以發送任何消息到delegate變量,因爲它的類型是id

你寫這樣的:

[delegate spend:self]; 

編譯器開啓到這一點的objc_msgSend函數的調用,就像這樣:

objc_msgSend(delegate, @selector(spend:), self); 

在運行時,則objc_msgSend函數搜索的方法表對於與選擇器spend:相關聯的方法,其類別(及其超類)爲delegate

順便提及,我們通常聲明delegate變量是這樣的:

id<TransactionDelegate> delegate; 

這告知編譯器,delegate將是符合TransactionDelegate協議的對象。此聲明將幫助Xcode在您嘗試向delegate發送消息時爲您提供更好的自動完成功能。如果以這種方式聲明你的setter方法或屬性,編譯器在編譯時也會檢查你是否將它設置爲符合協議的對象。

+0

謝謝!哇,那是一個非常強大的功能。我的意思是我知道id類型是這個抽象對象類型,但不知道它可以調用它自己的類的方法。 – 2013-03-11 19:05:28

1

好問題。獲取Obj-C和其他編譯語言之間的主要區別之一。

您可以發送任何消息到您喜歡的任何Objective-C對象。消息發送將嘗試由稱爲運行時庫的庫來解決,並在運行時發生。在編譯時,如果你的對象類型不是通用的id,一些IDE可能會將其標記爲可能的用戶錯誤。

在運行時,運行時庫將查找匹配方法,然後查看類是否有需要它的回退處理程序,並且作爲最後的手段會拋出異常。用戶代碼可以很好地捕捉到這個異常,並將其視爲正常情況。

+0

那麼通常分配給委託對象的id類型是什麼?這是Obj-C的標準戰術/程序嗎? – 2013-03-12 14:42:54

相關問題