ivarへのポインタは、ARCの「id__autoreleasing *」引数に渡すことはできません。これは、そのようなパスバイライトバックの形式が正しくないためです。ARC仕様のそれぞれのセクションには、パスバイライトバックの法的形式がリストされています。ここで適用できるのは、
&var、ここでvarは、保持可能なオブジェクトを使用した自動保存期間のスカラー変数です。
したがって、自動保存期間(ローカル変数)のみが許可されます。
これが無効である理由:ここでの理由は、古いコードとの互換性であると確信しています。
1)失敗した場合のエラーライトバックのみを確認する必要があります。成功した場合、エラーポインタの内部に何があるかはまったく保証されません。
2)一般に、ライトバック値を使用するかどうかは、メソッドのコントラクトによって異なります。これはコンパイラがチェックできないものです。
&error
これは、 (NSError * __autoreleasing *
)のタイプをライトバックのタイプ(NSError **
として解釈される)に一致させるコードのバージョンですNSError * __autoreleasing *
。がYESの場合ok
、エラー値は変更されません。
NSError * __autoreleasing error;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK) {
// use error
}
ただし、これら__autoreleasing
は醜いため、コンパイラは、あちこちで使用する代わりに、 (ただしローカルの)変数(デフォルトの所有権)も__autoreleasing
渡すことができます。__strong
NSError *error;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK) {
// use error
}
ドキュメントによると、それは次のように書き直されます:
NSError * __strong error;
NSError * __autoreleasing tmp = error;
BOOL OK = [myObject performOperationWithError:&tmp];
error = tmp;
if (!OK) {
// use error
}
まったく問題ありません。エラーは成功した場合にのみ使用されます。
__strong
次に、インスタンス変数を見てみましょう_error
。なぜコンパイラはそれを許可しないのですか?書き換えは次のようになります。
NSError * __autoreleasing tmp = _error;
BOOL OK = [myObject performOperationWithError:&tmp];
_error = tmp;
if (!OK) {
// use error
}
ここでの問題は、ライトバックtmp
が常に使用され(インスタンス変数に割り当てられ)、ライトバックはエラーの場合にのみ使用されるというメソッドのコントラクト(または一般にメソッドのドキュメントに記載されているもの_error
)を無視することです。最後のエラーをインスタンス変数に割り当てる安全な方法は次のとおりです。
NSError * __autoreleasing tmp = _error;
BOOL OK = [myObject performOperationWithError:&tmp];
if (!OK) {
_error = tmp;
// use error
} else {
_error = nil; // Make sure that _error is nil if there was no error.
}
そして、それはエラーを返すCocoaのメソッドの慣習にのみ当てはまります。一般に、コンパイラがメソッドがどのように機能するかを判断する方法はid *
ありません。:異なる規則を使用する古いメソッドが存在する可能性があります。したがって、本当にライトバックをインスタンス変数に格納したい場合は__strong
、現在、自分でさらに1マイル歩く必要があり、これが変わることはないと思います。