2012-01-06 9 views
6

私はMVC用のモデルを構築していますが、Apple Documentation「値として可変オブジェクトを設定しても、NSUserDefaultsから返される値は不変です」と違う現象が発生しています。、[[NSUserDefaults standardUserDefaults] objectForKey:@ "key"]はの配列をに返します。NSUserDefaultsが可変配列を返しています

Xcode 4D199のiOS用に空のアプリケーションを作成して、条件を再作成し、自分のプロジェクトで他の要因が原因ではないことを確認しました。

示すように、私はNSMutableArrayの設定しています:

- (void)setupTest 
{ 
    NSMutableArray *mutableArray = [[NSMutableArray alloc] init]; 
    [mutableArray addObject:@"one"]; 
    [mutableArray addObject:@"two"]; 

    [[NSUserDefaults standardUserDefaults] setObject:mutableArray forKey:@"mutableArray_01"]; 
    [[NSUserDefaults standardUserDefaults] synchronize];  
} 

をして、示したように、私は、オブジェクトを取得しています:

- (void)checkTest 
{ 
    NSMutableArray *mutableArrayInCheck = nil; 
    id whatIsThis = [[NSUserDefaults standardUserDefaults] objectForKey:@"mutableArray_01"]; 
    if([whatIsThis isKindOfClass:[NSMutableArray class]]) 
    { 
     NSLog(@"The array is mutable."); 
     mutableArrayInCheck = (NSMutableArray *)whatIsThis; 
    } 
    if([whatIsThis isKindOfClass:[NSArray class]]) 
    { 
     NSLog(@"The array is immutable."); 
    } 
    if ([whatIsThis isMemberOfClass:[NSMutableArray class]]) 
    { 
     NSLog(@"The array is a member of NSMutableArray class"); 
    } 

    if (mutableArrayInCheck) 
    { 
     [mutableArrayInCheck addObject:@"three"]; 
     NSLog([mutableArrayInCheck description]); 
    } 
} 

、アップルのドキュメントによると、人はにコンソールを期待します不変行のみを表示します。私は、コードを実行すると、次の行がコンソールに表示されます。しかし:

2012-01-05 18:47:33.328 Tester_01[78533:f803] The array is mutable. 
2012-01-05 18:47:33.348 Tester_01[78533:f803] The array is immutable. 
2012-01-05 18:47:33.349 Tester_01[78533:f803] (
    one, 
    two, 
    three 
) 

だから私はここで行方不明です何かがある場合、私は疑問に思って。追加情報については

、テストを実行するコードは、図示のようにされています。最初は、私はYESsetupKeyセットでプロジェクトを実行した

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    BOOL setupKey = NO; 
    if (setupKey) 
    { 
     [self setupTest]; 
    } 
    BOOL checkKey = YES; 
    if (checkKey) 
    { 
     [self checkTest]; 
    } 

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 
    // Override point for customization after application launch. 
    self.window.backgroundColor = [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 

。最初の実行後、私はsetupkey to を変更しました。 setupKeyNOに設定されていた間、コンソールログは結果です。どう考えているか教えてください。

+1

私は、彼らはちょうどあなたがすべきと言って意味を推測します可変配列を得ることに数えられません。私のプロジェクトでは、 '[NSArray arrayWithArray:mutableArray]を実行するだけでオーバーヘッドが追加されるため、NSMutableArrayポインタをNSArrayポインタに割り当てることはほとんどありません。 – mvds

+1

ちょうど推測:あなたが変更可能な配列をユーザーのデフォルトに追加した後で、再設定しないでそれを読んだ後に、アプリケーションを再起動しましたか?私はイメージングを行うことができます。オブジェクトは1つのセッション中に同じ状態を保ち、シリアル化されてディスクに書き込まれ、再び読み込まれるまで保持されます。 – vikingosegundo

+0

はい、質問の最後に説明したように、*** setupKey ***を** YES **に設定すると、アプリケーションを初めて実行するときに変更可能な配列を設定します。その後、*** setupKey ***を** NO **に設定し、アプリケーションを再起動して上記のコンソール出力を取得しました。 – Jin

答えて

2

厳密に言えば、あなたは正しいです。 "返される値は不変です"というステートメントは混乱しています。これは、可変オブジェクトを取得するように見えるので、は不可能です。です。ただし、この文は「返される値は可変であることが保証されていない可能性があります」と読み替える必要があります。したがって、可変配列を格納していても、値を読み取ったときに、NSArrayオブジェクト(NSMutableArrayの可変オブジェクトのオブジェクトである可能性がありますが、これは保証されていない可能性があります。配列の内容)。メソッドisKindOfClass

+0

確かに。この実装に依拠することは、OSXやiOSの今後のリリースでも変更される可能性があるため、非常に悪い考えです。 –

+0

良い点。まあ、ドキュメントは、それが本当に事実である場合、あなたがそれをどのように記述したかを再記述すべきです。とにかく、この時点でNSUserDefaultsからNSMutableArrayを取得するたびに新しいNSMutableArrayを初期化するための注意を払い、内容を抽出する必要があります。 – Jin

1

は、次の段落では、ドキュメント

である

クラスクラスタには適していないクラスクラスタによって表されるオブジェクトに対して、この方法を使用する場合は注意してください。クラスクラスターの性質上、戻ってくるオブジェクトは、必ずしも期待したタイプではないかもしれません。クラスクラスターを返すメソッドを呼び出す場合、メソッドによって返される正確な型は、そのオブジェクトで何ができるかを示す最も良い指標です。この方法は、NSArrayのオブジェクトへのポインタを返した場合、次のコードに示すように、たとえば、あなたは、配列が変更可能かどうかを確認するために、このメソッドを使用しないでください。

// DO NOT DO THIS! 
//if ([myArray isKindOfClass:[NSMutableArray class]]) 
//{ 
// Modify the object 
//} 
関連する問題