First I read this article
I think I should use "copy" in my programe.
Problem is using NSMutableDictionary copy it will terminate.
***** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘-[__NSCFDictionary removeAllObjects]: mutating method sent to immutable object’**
I have no idea about "mutating method sent to immutable object".
I didn’t set NSDictionary to NSMutabledictionary pointer.
Here is my code
.h file
@interface Button : NSObject {
@private
NSString* gID;
NSString* gBackColor;
NSString* gIconImage;
int gIndex;
BOOL gEnable;
BOOL gVisible;
NSString* gText;
NSMutableDictionary* gEvents;
BOOL gUseCircle;
}
@property (nonatomic,copy) NSString *ID;
@property (nonatomic,copy) NSString *BackColor;
@property (nonatomic,copy) NSString *IconImage;
@property int Index;
@property BOOL Enable;
@property BOOL Visible;
@property (nonatomic,copy) NSString *Text;
@property (nonatomic,getter=getEvents,retain) NSMutableDictionary *Events;
@property BOOL UseCircle;
@end
.m file
@implementation Button
@synthesize ID = gID;
@synthesize BackColor = gBackColor;
@synthesize IconImage = gIconImage;
@synthesize Index = gIndex;
@synthesize Enable = gEnable;
@synthesize Visible = gVisible;
@synthesize Text = gText;
@synthesize Events = gEvents;
@synthesize UseCircle = gUseCircle;
-(NSMutableDictionary*) getEvents
{
if (!gEvents)
{
gEvents = [[NSMutableDictionary alloc] initWithCapacity:20];
}
return gEvents;
}
- (id) init
{
self = [super init];
if (self != nil)
{
gID = @"";
gBackColor = @"";
gIconImage = @"";
gIndex = 0;
gText = @"";
gUseCircle = NO;
}
return self;
}
- (void) dealloc
{
[gID release];
[gBackColor release];
[gIconImage release];
[gText release];
[gEvents removeAllObjects];
[gEvents release];
gEvents = nil;
[super dealloc];
}
And implement
tBtnXML.Events = [self SplitEvents:tNode];
SplitEvents function:
-(NSMutableDictionary*) SplitEvents:(NSDictionary*)pEvents
{
NSMutableDictionary *tEvents = [[NSMutableDictionary alloc] initWithCapacity:5];
// code blabla
//.
//.
//.
[tEvents setObject:tEvent forKey:[NSNumber numberWithInt:tEventName]];
[tEvent release];
return [tEvents autorelease];
}
But I chage NSMutableDictionary* gEvents property from copy to retain , it execute normal.
Colud anyone tell me what’s wrong with my code?
If my code is incorrect with dealloc,please tell me.
Thank you appriciate.
Yes, So I fixed my setter:
-(void) setEvents:(NSMutableDictionary*) pEvents
{
NSMutableDictionary* tNewDict = [pEvents mutableCopy];
[gEvents removeAllObjects];
[gEvents release];
gEvents = tNewDict;
}
This work with no error.
It helps me a lot.
But I can’t vote up >"<~
So thank you Bavarious 🙂
In general, mutable properties should be
retaininstead ofcopy. When you declare a property as beingcopy, the synthesised setter method sends-copyto the object that’s being assigned to the property. In the case of mutable objects (e.g.NSMutableDictionary), sending-copyto them makes an immutable copy, effectively creating an object of immutable type (e.g.NSDictionary) instead.So in:
the synthesised setter sends
-copyto[self SplitEvents:tNode], thus creating an immutable copy of that dictionary (i.e., anNSDictionaryinstance), and assign it togEvents. This is the cause of your error:gEventsis declared asNSMutableDictionarybut points to anNSDictionaryinstead.For the record, mutable classes usually declare a
-mutableCopymethod that does make a mutable copy. It is not used by declared properties, though. If you do not want to useretain, you need to implement a custom setter that uses-mutableCopy.