-init
および+initialize
は全く異なるものです。最初はインスタンスを初期化するためのものです。 2番目はクラスを初期化するためのものです。
どのクラスにもメッセージが初めて送信されると、ランタイムは+initialize
をとそのスーパークラスに必ず呼び出します。スーパークラスは、どのサブクラスも自身を初期化する前に準備が必要であるため、最初に初期化されます。その時YourSubclass
がメッセージとして送られるので、最初
、のような何かを行う可能性がありますランタイムは:それはおそらく、これはNSObject
がメッセージとして送られるのは初めてだろうと非常に低いですので、ものの
[NSObject initialize];
[YourClass initialize];
[YourSubclass initialize];
(それはdoesnのトンこの時点で初期化する必要があります。それはちょうど、説明のためです。)
YourSubclass
が+initialize
を実装していない場合は、上記のよう[YourSubclass initialize]
の呼び出しは、実際に+[YourClass initialize]
を呼び出します。それは仕事での通常の継承メカニズムです。それは+[YourClass initialize]
が呼び出された2回目になります。
+initialize
の方法で行われた作業は、通常は一度だけ行うべきものなので、ガードif (self == [TheClassWhoseImplementationThisMethodIsPartOf class])
が必要です。また、その作業では、多くの場合、書かれている現在のクラスを参照すると仮定しているため、ガードの理由にもなります。
2番目の答えは、+setKeys:triggerChangeNotificationsForDependentKey:
メソッドでKVO依存キーを登録する旧式のメカニズムである例外を示しています。このメソッドは、サブクラスではなく、呼び出された実際のクラスに固有です。あなたはそれを避け、最新の+keyPathsForValuesAffectingValueForKey:
または+keyPathsForValuesAffecting<Key>
メソッドを使用する必要があります。古い方法を使用する必要がある場合は、その部分をガードの外に置きます。また、そのようなクラスのサブクラスは、通常行われていないsuper
にコールスルーする必要があります。
更新:ランタイムがすでにスーパークラスを初期化しているため、
+initialize
方法は、通常super
に通じ呼び出すべきではありません。スーパークラスが古いメカニズムを使用して従属キーを登録することがわかっている場合にのみ、すべてのサブクラスはスーパーにコールスルーする必要があります。
-init
の場合、ランタイムはあなたの呼び出し前に自動的にスーパークラスのinitメソッドを呼び出すわけではないので、同じ心配はありません。実際に、initメソッドがsuper
にコールしない場合、インスタンスのスーパークラスの「一部」は何も初期化されません。
initとinitializeはお互いに関係ありません。 – rmaddy
@rmaddy '-init'の中に' self = [super init]; 'があり、これは親の' + initialize'を呼びますか? – makaed
あなたは正しくありません。初期化は、他のクラスまたはインスタンスメソッドが呼び出される前にクラスごとに1回呼び出されます。 – rmaddy