@property保留或复制

时间:2011-04-11 02:16:45

标签: objective-c copy properties nsmutabledictionary retain

首先我读了这个article

我想我应该在我的程序中使用“复制”。 问题是使用NSMutableDictionary复制它将终止。

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

我不知道“发送到不可变对象的变异方法”。 我没有将NSDictionary设置为NSMutabledictionary指针。

这是我的代码



.h文件

@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文件

@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];
}



并实施

tBtnXML.Events = [self SplitEvents:tNode];



SplitEvents功能:

-(NSMutableDictionary*) SplitEvents:(NSDictionary*)pEvents
{
    NSMutableDictionary *tEvents = [[NSMutableDictionary alloc] initWithCapacity:5];
    // code blabla
    //.
    //.
    //.
    [tEvents setObject:tEvent forKey:[NSNumber numberWithInt:tEventName]];
    [tEvent release];



            return [tEvents autorelease];
}


但是我将NSMutableDictionary * gEvents属性从copy复制到retain,它执行正常。

Colud有人告诉我我的代码有什么问题吗?

如果我的代码与dealloc不正确,请告诉我。

谢谢appriciate。





是的,所以我修理了我的二传手:

-(void) setEvents:(NSMutableDictionary*) pEvents
{
    NSMutableDictionary* tNewDict = [pEvents mutableCopy];
    [gEvents removeAllObjects];
    [gEvents release];
    gEvents = tNewDict;
}


这项工作没有错误。

它给了我很多帮助。

但我不能投票>“<〜

谢谢你巴伐利亚:)

1 个答案:

答案 0 :(得分:6)

通常,可变属性应为retain而不是copy。当您将属性声明为copy时,合成的setter方法会将-copy发送到分配给该属性的对象。对于可变对象(例如NSMutableDictionary),向它们发送-copy使成为不可变副本,有效地创建了一个不可变类型的对象(例如NSDictionary)代替。

所以:

tBtnXML.Events = [self SplitEvents:tNode];

合成的setter将-copy发送到[self SplitEvents:tNode],从而创建该字典的不可变副本(即NSDictionary实例),并将其分配给gEvents。这是导致错误的原因:gEvents被声明为NSMutableDictionary,但却指向NSDictionary

对于记录,可变类通常声明一个-mutableCopy方法,它确实制作了一个可变副本。但是,它不被声明的属性使用。如果您不想使用retain,则需要实施使用-mutableCopy的自定义设置器。