有時候會想用 *.plist 來儲存資料,這時候若是從檔案內讀進資料建立 NSMutableDictionary 時,某個資料是
NSMutableString 時,想要對他 setString 時,就會出現 'Attempt to mutate immutable
object with setString:' 的錯誤訊息,程式也就不正常結束了。
猜是可能是從檔案讀進來建的資料結構有問題,如只轉成 NSString 而已,雖然我有用 [obj isKindOfClass:[NSMutableString class] ] 來判斷出來是 NSMutableString
狀態,但在這個情境下還是會出錯。
測試程式如下:
UntitledAppDelegate.h
#import <UIKit/UIKit.h>
@interface UntitledAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@end
UntitledAppDelegate.m
#import "UntitledAppDelegate.h"
@implementation UntitledAppDelegate
@synthesize window;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *db_path = [[NSString alloc] initWithString:[documentsPath
stringByAppendingPathComponent:@"test.plist"]];
NSMutableDictionary *db;
if( [[NSFileManager defaultManager] fileExistsAtPath:db_path] )
db = [[NSMutableDictionary alloc]
initWithContentsOfFile:db_path];
else
db = [[NSMutableDictionary alloc] init];
if( [db objectForKey:@"test"] == nil )
{
NSLog( @"Init test" );
[db setValue:[[NSMutableString alloc] initWithString:@"1"]
forKey:@"test"];
}
else if( [[db objectForKey:@"test"] isKindOfClass:[NSMutableString
class] ] )
{
NSLog( @"set test from disk data" );
[[db objectForKey:@"test"] setString:@"2"];
}
else
{
NSLog(@"ERROR");
}
if( [db objectForKey:@"test"] && [[db objectForKey:@"test"]
isKindOfClass:[NSMutableString class] ] )
{
NSLog( @"set test from memory" );
[[db objectForKey:@"test"] setString:@"2"];
}
[db writeToFile:db_path atomically:YES];
// Override point for customization after application launch
[window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[window release];
[super dealloc];
}
@end
執行結果:
第一次:
[Session started at 2010-05-12 09:06:16 +0800.]
2010-05-12 09:06:17.170 Untitled[1017:207] Init test
2010-05-12 09:06:17.171 Untitled[1017:207] set test from memory
再跑第二次:
[Session started at 2010-05-12 09:06:22 +0800.]
2010-05-12 09:06:23.488 Untitled[1022:207] set test from disk data
2010-05-12 09:06:23.489 Untitled[1022:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with setString:'
2010-05-12 09:06:23.494 Untitled[1022:207] Stack: (
29287515,
2479863049,
29371451,
29371290,
723866,
9974,
2721159,
2759094,
2747188,
2729599,
2756705,
37383513,
29072256,
29068360,
2723349,
2760623,
9252,
9106
)
目前暫時的解法,只好把它刪除再重新設定了!
原本:
[[db objectForKey:@"test"] setString:@"2"];
更新:
[db removeObjectForKey:@"test"];
[db setValue:[[NSMutableString alloc] initWithString:@"2"] forKey:@"test"];
沒有留言:
張貼留言