10

複数回呼び出されている+initializeメソッドがありますが、その理由がわかりません。

ドキュメントによると、すべてのクラス (およびサブクラス) に対して 1 回呼び出されます。

これは私が使用しているコードです:

@interface MyClass : NSObject

@end

static NSArray *myStaticArray;

@implementation MyClass

+ (void)initialize
{
  myStaticArray = [NSArray array];
}

@end

(明らかに他のコードがありますが、それは関連する部分です)。

のサブクラスはありませんMyClass。派手なことは何もしません。+initialize は、アプリケーションが起動されたときに 1 回呼び出されます (NSApplication のデリゲートは、myStaticArray にディスクからのデータを入力するように指示します)。+initialize が 2 回目に呼び出されます。これは、ユーザーがこのクラスに関連するメニュー項目を初めて選択したときです。

コードを追加dispatch_once()しただけinitializeで、明らかに問題が解決しました。しかし、私は何が起こっているのか理解していませんか?サブクラスがないのに、なぜ複数回呼び出されるのですか?

これは、+initialize が初めて呼び出されたときのスタック トレースです。

+[MyClass initialize]
_class_initialize
objc_msgSend
-[MyAppDelegate applicationDidBecomeActive:]
_CFXNotificationPost
NSApplicationMain
main
start

そして、これが2番目の呼び出しです:

+[MyClass initialize]
_class_initialize
NSApplicationMain
main
start

ご覧のとおり、私のコードは +initialize への 2 回目の呼び出しをトリガーしていないようです (スタック トレースには何もありません)。クリアされた静的配列の内容を表示するウィンドウを表示した直後に発生し+initializeます (ウィンドウには配列の内容が表示されますが、その直後に配列は空になります)。

4

3 に答える 3

25

+initialize動的に作成されたクラスを含め、(メッセージによって) 最初に参照されたときに各クラスに送信されます。実行を複数回トリガーすることに対するランタイムの保護はありません。サブクラスが初期化されているが を実装していない場合+initializesuperチェーンの上位にあるサブクラスが再度呼び出されます。

直交的に、自動 KVO は、監視対象インスタンスのクラスの動的に派生したサブクラスを作成することによって実装されます。そのサブクラスは+initialize他のクラスと同じように d であるため、親クラスの+initialize.

ランタイムは、これを防ぐための対策を講じることができます。ただし、+initializeは複数回実行される可能性があると常に文書化されているため、追加された複雑さ (KVO クラスが頻繁に出入りすることを考えると、驚くほど複雑になる可能性があります) は、努力する価値があるとは見なされません。

現在推奨されているパターンは次のとおりです。

+ (void) initialize
{
      static dispatch_once_t once;
      dispatch_once(&once, ^{
        ... one time initialization here ...
      });
}
于 2013-01-02T16:46:36.723 に答える
3

+initialize継承チェーンの各クラスに対して呼び出されるため、同じスーパークラス (またはスーパークラスとそのサブクラスの 1 つ) を共有する 2 つのクラスを初期化すると、スーパークラスの+initializeメソッドが 2 回呼び出されます。

それが理由でしょうか?

于 2013-01-01T12:30:14.423 に答える
0

1.サブクラスの前にスーパークラスで +initialize メソッドを呼び出すランタイム

2.サブクラスにメソッドがない場合、親クラスの初期化メソッドが呼び出されます。

3.初期化メソッド +(void)initialize{ を常に記録する方法を使用する

if(self==[Car Class]){

//initialize here your static var
}  
}

明確な理解のために、この投稿を読んでください+(void)initialize

于 2015-02-26T12:48:48.427 に答える