2

fe (メッセージメカニズムをより明確に理解するためだけに)私はクラスを持っています

MyClass.h

@interface MyClass : NSObject {
   int ivar1;
   int ivar2;
}

+ (id)instance;

@end

MyClass.m

static MyClass* volatile _sInstance = nil;

@implementation MyClass

+ (id)instance {
       if (!_sInstance) {
       @synchronized(self) {
           if (!_sInstance) {
               _sInstance = [[super allocWithZone:nil] init];
           }
       }
   }
   return _sInstance;
}

@end

を呼び出すと、実際にはobjc_msgSendで何が送信され[super allocWithZone:nil]ますか?

objc_msgSend([MyClass class], "allocWithZone", nil)またはobjc_msgSend([NSObject class], "allocWithZone", nil)

実際には、それが呼び出されたと思います。objc_msgSend(self, "allocWithZone", nil)その場合self == [MyClass class];

ivar1 と ivar2 のメモリが確実に割り当てられるようにしたい。

クラス メソッドで super を呼び出すと、objc_msgSend() 関数で "self" 引数が渡されますが、この場合は子のクラス オブジェクトです。allocWithZone は、子クラス オブジェクトを「見て」、ivar1 と ivar2 に割り当てる必要があるメモリの量を確認します。

ありがとう!

4

1 に答える 1

3

へのメッセージはすべてsuper、コンパイラによってobjc_msgSendSuper(not objc_msgSend) に変換されます。最初の引数は、構造体へのポインターです。構造体には、現在の実装のスーパー クラスへのポインターと、レシーバーへのポインターが含まれます。前者は実行時にオーバーライドされた実装を検索するために必要であり、後者は最初の引数として使用されます。

クラス メソッドの場合、レシーバーは再びクラス ポインターですが、super_class. あなたの場合、レシーバーはMyClassポインターですが、super_classポインターはNSObject.

2 つの補足事項: 最もファンシーなシングルトンの作成に力を注ぐことはお勧めしません。独自のインスタンスを作成するか、提供された共有インスタンスを使用するかは、開発者に任せたほうがよいでしょう。また、ダブルチェックのロックが壊れていることに注意してください。

于 2013-08-15T09:37:48.753 に答える