3

クラスのプロパティをヘッダーファイルで宣言しています。

@property (readonly) NSArray *pages

それが私がそれを公に公開したい方法です。内部的には、NSMutableArrayとして割り当てて、そこから何かを追加/削除できるようにします。しかし、そのためには、毎回型キャストを行う必要があります。これを行うためのより良い方法はありますか?ありがとう

4

2 に答える 2

3

あなたのアプローチは本当に悪いです。動的コンテンツを含む可変配列を公開することを主張する場合は、不変コピーを返すようにゲッターを変更します。そうしないと、高速列挙中に奇妙な副作用と突然変異の例外が発生します。

于 2012-09-26T00:51:24.223 に答える
2

これに対する解決策はありません。毎回キャストするか、異なるプロパティを使用する必要があります。2番目のアプローチのサンプルを次に示します。

@interface MyClass : NSObject
@property (nonatomic, strong, readonly) NSArray *pages;
-(void)addObject:(id)obj;
@end

@interface MyClass()
@property (nonatomic, strong, readwrite) NSMutableArray *mPages;
@end

@implementation MyClass
-(id) init {
    self = [super init]
    if (self){
        _mPages = [NSMutableArray array];
    }
    return self;
}
-(NSArray*)pages {
    return [NSArray arrayWithArray:self.mPages];
}
-(void)addObject:(id)obj {
    [self.mPages addObject:obj];
}
@end


int main(int argc, char *argv[]) {
    @autoreleasepool {
        MyClass *m = [MyClass new];
        [m addObject:@"x"];     // the collection is mutable
        NSLog(@"%@",[m pages]); // but only accessible as an immutable copy
    }
}

コレクションに頻繁にアクセスする場合、これはコストがかかり、内部の変更可能なコレクションと同期していない可能性があります(コピーを反復処理するときに変更される可能性があります)。

コピーは、不変クラス(NSArray)を装った内部可変インスタンス(NSMutableArray)を返すことを回避できますが、次のリスクが発生します。

  • クライアントは可変にキャストして変更できます。
  • 内部コピーが変更される可能性があります。これにより、反復している場合にアプリケーションがクラッシュしたり、インデックスが範囲外の例外が発生したりする可能性があります。

次のイディオムでは問題が解決しないことに注意してください。

@interface MyClass : NSObject
@property (nonatomic, strong, readonly) NSArray *pages;
@end

@interface MyClass()
@property (nonatomic, strong, readwrite) NSMutableArray *pages;
@end

これにより、変数を設定できますが、インターフェイスで宣言されているクラスとは異なるクラスとして使用することはできません。言い換えれば、それはあなたにすべての使用でキャストすることを強制します:

[(NSMutableArray*)pages addObject:@"x"];
于 2012-09-26T00:45:47.703 に答える