2012-01-04 48 views
1
使用的setObject

当我收到异常:错误的NSMutableDictionary

- [__ NSCFDictionary的setObject:forKey:]:突变方法发送到不可变的对象”

有问题的行是:

[delegate.sharedData.dictFaves setObject:@"test" forKey:@"4"]; 

代表在MyViewController.m从而初始化:

delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 

这是我的代表是如何在AppDelegate.h定义:

#import "CommonData.h" 
... 
@interface AppDelegate : UIResponder <UIApplicationDelegate> 
{ 
    NSString *tempFave; 
    CommonData *sharedData; 
} 
@property (strong, nonatomic) NSString *tempFave; 
@property (strong, nonatomic) CommonData *sharedData; 

sharedData在AppDelegate.m这样初始化:

#import "AppDelegate.h" 
... 
@implementation AppDelegate 
@synthesize sharedData; 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    sharedData = [[CommonData alloc] init]; 
    return YES; 
} 

sharedData在CommonData.h定义:

@interface CommonData : NSObject 
{ 
    NSMutableDictionary *dictAffirms; 
    NSMutableDictionary *dictFaves; 
} 
@property (nonatomic, copy) NSMutableDictionary *dictAffirms; 
@property (nonatomic, copy) NSMutableDictionary *dictFaves; 

共享数据执行文件CommonData.m:

#import "CommonData.h" 
... 
@implementation CommonData 

@synthesize dictAffirms; 
@synthesize dictFaves; 

@end 

我已经声明CommonData的成员是可变的。显然这是不够的。为了写入CommonData中的字典,还必须做些什么?

+0

你在哪里分配init的NSMutableDictionaries。此外,这些都是艾瓦尔 - 你是否将这些属性公之于众? – bryanmac 2012-01-04 00:57:59

+0

我编辑我的帖子,包括CommonData实现。你会看到没有构造函数。所以当'sharedData = alloc/init'这行时,我没有写出一个包含NSMutableDictionary alloc/init的构造函数。这是问题吗? – Bassman 2012-01-04 15:21:18

+0

我们通常不会在objective-c中使用术语“构造函数”。它被称为初始化程序或-init方法。你不需要有一个初始化器。但是如果dictFaves将会有一个值,你必须从某处指定一个值。如果您指定了不可变字典,则会出现此问题。随意使用-mutableCopy方法将NSDictionary转换为NSMutableDictionary(记住在不使用ARC时分配给保留属性时自动释放副本)。 – 2012-01-05 20:25:16

回答

2

在尝试写入由plist填充的字典之前,我曾看到过此错误。如果你使用

yourMutableDictionary = [someDataSource objectForKey:@"someKey"]; 

你的字典将是不可变的,即使它被声明为可变。改用

yourMutableDictionary = [someDataSource mutableArrayValueForKey:@"someKey"]; 

,你的问题就会迎刃而解,假设这其实您的问题。这可能是这样的:

yourMutableDictionary = [[NSDictionary alloc] init]; 

yourMutableDictionary = [NSDictionary new]; 

,你只是不小心创建一个不可改变的对象,这是几乎同样的问题上面,只是不同。

很高兴看到用于初始化NSMutableDictionaries的代码。

编辑:也许尝试这样的事情,因为我很好奇结果会是什么。而不是使用:

[delegate.sharedData.dictFaves setObject:@"test" forKey:@"4"]; 

尝试

NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithDictionary:delegate.sharedData.dictFaves]; 
[dict setObject:@"test" forKey:@"4"]; 
delegate.sharedData.dictFaves = dict; 
[dict release]; 
+0

请看我上面的编辑。我包含了整个.m文件。你会看到没有NSMutableDictionaries的初始化。那么我在哪里启动它们:在CommonData实现文件或Delegate类中?我意识到这是一个愚蠢的问题,但我只是画空白。 – Bassman 2012-01-05 18:17:42

+0

你可以在你创建sharedDict属性的地方发布代码吗? – 2012-01-05 22:33:33

+0

我添加了创建属性的代码。我还充实了其他代码并重新编译了它。希望现在更容易阅读。感谢您的兴趣到目前为止.... – Bassman 2012-01-06 15:08:33

1

你已经声明dictFaves是可变的,但这并不意味着你实际上在那里存储了一个可变对象。检查你的初始化器。你可能有类似如下:

dictFaves = [[NSDictionary alloc] init]; 

如果是这样,您需要更改到NSMutableDictionary代替。

+0

会不会编译器警告? – 2012-01-04 01:40:08

+1

@Yar:现在的铿锵会。 GCC不会。 'alloc'和'-init'方法都是用'id'返回类型声明的,所以GCC不会关心你把它放入什么类型的变量(只要它是一个对象/指针)。 Clang很聪明,知道'alloc和'-init'实际上返回了接收者的实例类型,并且应该警告。 – 2012-01-04 01:41:06

+0

伟大的一点,我在想'NSDictionary字典',但并不是所有的方法都是可以互换的。 – 2012-01-04 01:49:27

1

你的问题是,这本词典的属性setter被声明为copy。 NSMutableDictionary的copy方法返回一个不可变的NSDictionary(通常,copy几乎总是返回一个不可变的对象)。因此,假设您使用标准的合成设置器,每次设置该属性时,都会在幕后分配错误的类型。相反,它应该是strong

+0

谢谢 - 将NSDictionary属性更改为'(nonatomic,strong)'做了诀窍。 – Bassman 2012-01-22 23:47:11