3

スタックオーバーフローに関する私の最初の質問ですので、優しくしてください。答えを探してみましたが、本当に助けが必要です。

問題は、ニールゴールドスタインのObjective-CforDummiesからの代表者について学ぶことです。

彼は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タイプのどれがそのメソッドを呼び出すかをどのように委任できますか?コンパイラは、それがどのオブジェクトであるかさえ知りません...

助けてください!

PS誰かが良いObjective-Cの本について何かアドバイスがあれば、私はそれを高く評価します。iPhoneの開発に取り掛かりたいのですが、まずObjective-Cの基本をよく理解する必要があると思いました。

ありがとう!

4

2 に答える 2

2

delegateはい、変数のタイプは。であるため、任意のメッセージを変数に送信できますid

あなたはこれを書いた:

[delegate spend:self];

objc_msgSendコンパイラはそれを次のように関数の呼び出しに変換します。

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

実行時に、objc_msgSend関数はのクラス(およびそのスーパークラス)のメソッドテーブルでdelegate、セレクターに関連付けられたメソッドを検索しますspend:

ちなみに、私たちは通常、次のdelegateように変数を宣言します。

id<TransactionDelegate> delegate;

これは、プロトコルdelegateに準拠するオブジェクトになることをコンパイラーに通知します。TransactionDelegateこの宣言は、にメッセージを送信しようとしているときにXcodeがより良いオートコンプリートを提供するのに役立ちますdelegate。この方法でsetterメソッドまたはプロパティを宣言するdelegateと、コンパイラはコンパイル時に、プロトコルに準拠するオブジェクトに設定していることも確認します。

于 2013-03-11T18:14:51.837 に答える
1

良い質問。Obj-Cと他のコンパイル言語の主な違いの1つを取得します。

任意のObjective-Cオブジェクトに任意のメッセージを送信できます。送信されたメッセージは、ランタイムライブラリと呼ばれるライブラリによって解決されようとします。これは実行時に発生します。コンパイル時に、汎用ID以外のオブジェクトタイプがある場合、一部のIDEは、ユーザーの間違いの可能性があるとしてフラグを立てる場合があります。

実行時に、ランタイムライブラリは一致するメソッドを探し、クラスにそれを必要とするフォールバックハンドラーがあるかどうかを調べ、最後の手段として例外をスローします。ユーザーコードはこの例外を非常にうまくキャッチし、通常の状況として扱うことができます。

于 2013-03-11T19:52:22.887 に答える