5

昔は、次のような init メソッドを書くように訓練されていました。

フー.h:

-(id) initWithInteger: (NSInteger) someNumber;

Foo.m:

-(id) initWithInteger: (NSInteger) someNumber {
    if ((self = [super init])) { 
       doSomeStuff;
    }
    return self;
 }

しかし、これらの id キャストは今やノーノーです。では、これらのメソッドはどのように見えるべきでしょうか?

編集:これはライブラリ用です。したがって、呼び出しコードがどのように見えるかはわかりません。

4

3 に答える 3

8

戻ることはノーノーだと言うのはなぜidですか?ARC仕様は言う

initメソッドはインスタンス メソッドである必要があり、Objective-C ポインター型を返す必要があります。さらに、戻り値の型が id ではなく、宣言するクラスのスーパークラスまたはサブクラスへのポインターでもない init メソッドの呼び出しを宣言または含む場合、プログラムは不正な形式です (メソッドがクラスで宣言されている場合)。 ) または呼び出しの静的受信者型 (プロトコルで宣言されている場合)。

さらに、使用ARCはファイルごとの決定であることに注意してください。つまり、ARC でコンパイルされたコードを ARC なしのコードで使用でき、その逆も可能です。ライブラリ用のヘッダファイルの場合は両方で使えるように準備しておく必要がありますが、非ARC用に用意すれば十分です。

于 2011-07-29T14:31:27.157 に答える
4

これが私が今やっていることです:

-(id) initWithInteger: (NSInteger) someNumber {
    self = [super init];
    if (self) { 
       doSomeStuff;
    }
    return self;
}

警告がなくなり、論理的には同等ですが、それほどエレガントではありません。

当たり前のことですが、私は今、ばかのように感じており、質問を読んで理解していませんでした。しかし、役立つかもしれない何かを指すこのリンクを見つけました。具体的には、セクション 5 で次のように述べています。

init メソッドはインスタンス メソッドである必要があり、Objective-C ポインター型を返す必要があります。さらに、戻り値の型が id ではなく、宣言するクラスのスーパークラスまたはサブクラスへのポインターでもない init メソッドの呼び出しを宣言または含む場合、プログラムは不正な形式です (メソッドがクラスで宣言されている場合)。 ) または呼び出しの静的受信者型 (プロトコルで宣言されている場合)。

それに基づいて、何もする必要がないように見えますが、これは理にかなっています。Apple でさえ、その開発者に対してそれほど残酷ではありません。コンパイルエラーが発生していますか? 私はまだ Lion にジャンプしていないので、ARC はまだ私のレーダーにはありません。

于 2011-07-29T12:59:33.893 に答える
0

昔は、次のような init メソッドを書くように訓練されていました。

フー.h:

-(id) initWithInteger: (NSInteger) someNumber;

Foo.m:

-(id) initWithInteger: (NSInteger) someNumber {
   if ((self = [super init])) { 
      doSomeStuff;
   }
   return self;
}

しかし、これらの id キャストは今やノーノーです。では、これらのメソッドはどのように見えるべきでしょうか?

それらはキャストではありません。そのコンテキストでは、その単純な構文はメソッドの戻り値の型を(NSInteger)宣言します。これは、後の部分でその引数の型を宣言するためです。

メソッドの戻り値の型を宣言するための構文は、ARC でも変更されていません。あなたが示したコードはまったく同じままです。

キャストは式であるため、ARC で禁止されている種類のキャストは、式のコンテキストでのみ発生します。たとえば、次のように言ったとします。

- (id) initWithCFThing:(CFThingRef)thing {
    if ((self = [super init])) {
        _thing = (NSThing *)thing; //Casts expression of type CFThingRef to object pointer type NSThing *; this is invalid
    }
    return self;
 }

代入式のキャストは、ブリッジ キーワードなしで CF オブジェクトから Objective-C オブジェクト ポインター (「保持可能なオブジェクト ポインター」) にキャストするため、無効です。逆も同様に無効です。

- (CFThingRef) CFThing {
    return _thing; //Implicitly casts expression of object pointer type NSThing *to type CFThingRef; this is invalid
}

他の方向の同じ問題:returnステートメントに指定された式は、保持可能なオブジェクト ポインターを、ブリッジ キーワードのない CF オブジェクト型にキャストします。

エラーがどこにあるかに注意してください。いずれの場合も、エラーは式にあります。 ininitWithCFThing:では、代入式内の明示的なキャスト式です。アクセサーでは、ステートメント内の式をメソッドの戻り値の型CFThingに暗黙的にキャストします。return

どちらの場合も、あなたの場合のように、メソッドのプロトタイプは完全に有効です。(CFThingRef)メソッドの戻り値の型または引数の型を(id)宣言するときは、ARC の有無にかかわらず有効です。キャスト自体が無効であるため、キャスト式としてのみ構文が無効です。

bridge キーワードを追加すると、キャスト式でコンパイラを満足させます。これは、コンパイラに何をしてほしいかを伝えているからです (bridge キーワードのない橋をまたぐキャストは無効です。コンパイラは、あなたが何を意味するのかを推測する必要があり、それを拒否するからです)。 )、ただし、あいまいではないため、型宣言では無効になります。ブリッジの交差は、引数の通過や戻りではなく、キャスト式 (存在する場合) で発生します。

于 2012-12-23T07:02:21.860 に答える