为什么它会导致“发送到不可变对象的变异方法”异常?

时间:2012-03-06 08:24:18

标签: objective-c ios

我刚刚开始进入iOS领域。我按照书中的一个例子,当我运行它时会抛出一个错误:

  

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:' - [__ NSCFDictionary setObject:forKey:]:发送到不可变对象的mutating方法'

下面列出的示例代码:

@interface MyXMLElement : NSObject

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *text;
@property (weak, nonatomic) MyXMLElement *parent;
@property (copy, nonatomic) NSMutableArray *children;
@property (copy, nonatomic) NSMutableDictionary *attributes;

@end

============================================

@implementation MyXMLElement

@synthesize name = _name;
@synthesize text = _text;
@synthesize parent = _parent;
@synthesize children = _children;
@synthesize attributes = _attributes;

-(id)init{
    self = [super init];
    if(self != nil){
        NSMutableArray *childrenArray = [[NSMutableArray alloc]init];
        self.children = [childrenArray mutableCopy];
        NSMutableDictionary *attributesDictionary = [[NSMutableDictionary alloc]init];
        self.attributes = [attributesDictionary mutableCopy];
    }
    return self;
}
@end

============================================

@interface MyXMLDocument : NSObject <NSXMLParserDelegate>

@property (nonatomic, strong) NSString *documentPath;
@property (nonatomic, strong) MyXMLElement *rootElement;
@property (nonatomic, strong) NSXMLParser *xmlParser;
@property (nonatomic, strong) MyXMLElement *currentElement;

-(BOOL)parseLocalXMLWithPath:(NSString *)paramLocalXMLPath;
@end    

============================================

@implementation MyXMLDocument

@synthesize documentPath = _documentPath;
@synthesize rootElement = _rootElement;
@synthesize xmlParser = _xmlParser;
@synthesize currentElement = _currentElement;

-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if (self.rootElement == nil){
        MyXMLElement *root = [[MyXMLElement alloc] init];
        self.rootElement = root; 
        self.currentElement = root;
    } else {
        MyXMLElement *newElement = [[MyXMLElement alloc] init];
        newElement.parent = self.currentElement;
        [self.currentElement.children addObject:newElement];
        self.currentElement = newElement;
    }
    self.currentElement.name = elementName;
    if ([attributeDict count] > 0){
        //this line will throw out a exception.
        [self.currentElement.attributes addEntriesFromDictionary:attributeDict];
    }
}

1 个答案:

答案 0 :(得分:2)

@property (copy, nonatomic) NSMutableDictionary *attributes;

这意味着合成方法-[MyXMLElement setAttributes:]将使用-copy方法复制其参数。这产生了一个不可变对象,即使参数是可变的。

尝试将其更改为:

@property (retain, nonatomic) NSMutableDictionary *attributes;

另外:此代码过于复杂且漏洞。

NSMutableDictionary *attributesDictionary = [[NSMutableDictionary alloc] init];
self.attributes = [attributesDictionary mutableCopy];

应该是:

self.attributes = [NSMutableDictionary dictionary];
这是什么书?太可怕了。