OS 2.2.1とOS 3の間のObjective-Cの変更は?
-
06-07-2019 - |
質問
OS 3用にアプリをコンパイルしようとすると、次のエラーが発生しました:
エラー:アクセサのタイプがプロパティのタイプと一致しません
エラーは、次のように定義されているアクセスしようとしたプロパティに対するものでした:
NSMutableArray *myArray
@property (readonly,nonatomic) NSArray* myArray;
プロパティは実装ファイルで@synthesizedになります。
これはOS 2.2.1では問題なく動作しましたが、OS 3.0では動作しません
ゲッターメソッドを自分で記述して問題を解決しました。
OS 2.2.1と3.0の間のObjective-Cの変更を知っている人はいますか? これらの変更に関するドキュメントはありますか?
API変更文書には、この問題に関する情報は含まれていないようです。
編集
プロパティにアクセスしようとするとエラーが発生します。
NSArray *anArray = myClass.myArray;
前述したように、この回避策を見つけました:ゲッターメソッドを自分で記述しますが、私が本当に望んでいるのは、この変更とAPI関連ではないその他の変更を説明するアップルのドキュメントです。
ご協力ありがとうございます
解決
これはコンパイラのバグです。
完全に指定していない場合でも、コードは次のようになります。
@interface Foo : NSObject {
NSMutableArray *objects;
}
@property (readonly, copy) NSArray *objects;
@end
@implementation Foo
@synthesize objects;
@end
残念ながら、コンパイラは objects
property の宣言と objects
instance変数の宣言との間で混同されています。 Objective-Cでは、プロパティとインスタンス変数が異なることに注意してください。プロパティはインスタンス変数によってバッキングできますが、実際にはクラスのパブリックインターフェイスの一部です。
この問題を回避するには、コードを変更して、インスタンス変数の定義をプロパティの定義から明確に分離します。たとえば、インスタンス変数の名前にプレフィックスを付けます。
@interface Foo : NSObject {
NSMutableArray *_objects;
}
@property (readonly, copy) NSArray *objects;
@end
@implementation Foo
@synthesize objects = _objects;
@end
このように、コンパイラは self.objects
のような式のプロパティとインスタンス変数について混乱しません(とにかくすべきではありませんが、明らかにそうです)。
避けられない応答を回避するために:Appleは、インスタンス変数のアンダーバープレフィックスを予約しません 。メソッド用に予約されています。とにかく、アンダーバーが気に入らない場合は、別のプレフィックスを使用してください。
他のヒント
編集:ピアレビューで不足していることが判明したため、元の回答は削除されました。この問題に関するChris Hansonのコメントを読んでください。私はそれがまだ有効だと思うので、ここに残りを残しています。
プロパティタイプを NSArray
として宣言しても、返されるオブジェクトは NSMutableArray
であり、可変メソッドは 定義されています。この方法でプロパティを宣言しても、誰かが誤って配列を変更することを 防止しません。
返された配列が可変でないことを確認したい場合は、元の例のようにプロパティを宣言し、独自のアクセサーをロールできます:
- (NSArray *)myArray { return [NSArray arrayWithArray:myArray]; }
これは、保持されない NSArray
を返すことに注意してください。永続化する必要がある場合、オブジェクトの所有権を取得するのは呼び出し側の責任です。
XCodeは以前はなかったものに対して警告とエラーを発行しているため、エラーが表示されています...
私はあなたがしていることを行うことはせいぜい警告であるべきだと主張します。外部世界に対して不変として配列を提示するが、クラス内でそれを変更可能にするあなたの試みを理解しています。可変配列を具体的に返すように構築された、異なる名前の別のアクセサーを検討することもできます。
まだObjective-C 2.0です。コンパイラは、この種の型がエラーを変更することを考慮して少し更新されるだけかもしれません。ほとんどエラーになります。少なくとも、あなたが書いたものを意味するものではないことを警告する必要があります。次に、警告を出さないようにキャストすることができますが、これは @synthesize
ステートメントではできません。
コードとシンセシスステートメントをコントローラーに正確に貼り付けただけで、エラーや警告はありませんでした。それはうまく構築されました。次に、ベースSDKを「Simulator 3.0」に設定し、ビルドを「Simulator 3.0 Debug」に設定します。このプロジェクトは2.2.1 SDKで開始され、昨日3.0 SDKをインストールしました。 Xcodeはバージョン3.1.3です。
更新:ああ、実際にプロパティを設定しようとすると、あなたが言及したエラーが表示されます。
self.myArray = [NSArray arrayWithObject:@"foo"];
明らかにこの動作を @synthesize
することはできず、独自のアクセサを作成する必要があります。
- (NSArray*)myArray {
return [NSArray arrayWithArray:myArray];
}
- (void)setMyArray:(NSArray*) pMyArray {
myArray = [NSMutableArray arrayWithArray:pMyArray];
}
これらのアクセサを入力しても、メッセージは消えませんでしたので、アクセスを次のように変更する必要がありました。
[self setMyArray:[NSArray arrayWithObject:@"foo"]];
カスタムアクセサーなしで上記の構文を使用しても機能しませんでした。
PSうわー、メッセージバブルも、ビルド結果ウィンドウのテキストもコピーできないことを他に悩まされている人はいますか?
つまり、これは本当にNSsynthとしてNSMutableArrayを公開することに満足していない@synthesize呼び出しと関係があります-単にgetMethodを実装しないのはなぜですか。
実際に考えてみると、それは幸せではないsetメソッドでなければなりません。NSArrayをNSMutableArrayに設定することはできません。
質問は次のとおりです。
OS 2.2.1と3.0の間でObjective-Cの変更を知っている人はいますか?
これらの変更に関するドキュメントはありますか?
決定的な答えは次のとおりです。
1)言語仕様に意図的な変更はありませんでしたが、コンパイラーおよびその他の開発者ツールは変更されました。クリスと彼の同僚は、これらの変更の専門家です。
2)おそらくそうではありません。変更は意図的ではないか、動作をドキュメントとよりよく一致させるために行われたためです。
「推測」としてクリスの答えをすぐに却下するべきではありません。クリスはアップルの開発者ツールに取り組んでいます。もっと好きな答えが得られるかもしれませんが、より専門的な答えは得られません。