@property 保留或复制

发布于 2024-10-31 14:58:35 字数 3372 浏览 3 评论 0原文

首先我读了这篇文章

我认为我应该在我的程序中使用“复制”。 问题是使用 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,它执行正常。

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

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

谢谢您的认可。





是的,所以我修复了我的设置器:

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

这项工作没有错误。

这对我有很大帮助。

但我不能投票>“<~

所以谢谢你巴伐利亚:)

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 :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

七禾 2024-11-07 14:58:35

一般来说,可变属性应该是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 的自定义 setter。

In general, mutable properties should be retain instead of copy. When you declare a property as being copy, the synthesised setter method sends -copy to the object that’s being assigned to the property. In the case of mutable objects (e.g. NSMutableDictionary), sending -copy to them makes an immutable copy, effectively creating an object of immutable type (e.g. NSDictionary) instead.

So in:

tBtnXML.Events = [self SplitEvents:tNode];

the synthesised setter sends -copy to [self SplitEvents:tNode], thus creating an immutable copy of that dictionary (i.e., an NSDictionary instance), and assign it to gEvents. This is the cause of your error: gEvents is declared as NSMutableDictionary but points to an NSDictionary instead.

For the record, mutable classes usually declare a -mutableCopy method that does make a mutable copy. It is not used by declared properties, though. If you do not want to use retain, you need to implement a custom setter that uses -mutableCopy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文