NSMutableDictionary 实例变量不保留循环外的键值

Posted

技术标签:

【中文标题】NSMutableDictionary 实例变量不保留循环外的键值【英文标题】:NSMutableDictionary instance variable not retaining key values outside of loop 【发布时间】:2011-07-12 23:38:39 【问题描述】:

很抱歉,如果这个问题已经出现,但我找不到任何可以解决我在这里遇到的具体问题的东西。

我在 ios 上的 Objective-c 中工作,我已经声明了一个 NSMutableDictionary 实例变量,它的一个属性,合成它,并在我的 init 方法中为它分配空间:

SettingsViewController.h

@interface SettingsViewController : UITableViewController <UIAlertViewDelegate> 
    NSMutableDictionary *settingsData;
    UISwitch *emailSwitch;
    UISwitch *phoneSwitch;
    NSMutableData *receivedData;


@property (nonatomic, retain) NSMutableDictionary *settingsData;
@property (nonatomic, retain) UISwitch *emailSwitch;
@property (nonatomic, retain) UISwitch *phoneSwitch;
@property (nonatomic, retain) NSMutableData *receivedData;

SettingsViewController.m 初始化方法

@synthesize settingsData, emailSwitch, phoneSwitch, receivedData;

# the initialization method, where settingsData is allocated
- (id)initWithStyle:(UITableViewStyle)style 
    self = [super initWithStyle:style];
    if (self) 
        self.navigationItem.title = @"Settings";
        [[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc]     initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(doneEditing:)] autorelease]];
        settingsData = [[NSMutableDictionary alloc] init];
    
    return self;

SettingsViewController.m 中使用 settingsData 的方法的药水(它只是一个非常简单的对格式化为 key=value& 的数据块的解析器):

NSMutableString *element = [NSMutableString string];
NSMutableString *value = [NSMutableString string];
bool cap_element = true;
char index;
for (int i = 0; i < [response length]; i++) 
    index = [response characterAtIndex:i];
    if (cap_element && index != '=') 
        [element appendFormat:@"%c", index];
        continue; // skip back to the top
    
    if (index == '=') 
        cap_element = false;
        continue;
    
    if (!cap_element && index != '&') 
        [value appendFormat:@"%c", index];
        continue;
    
    if (index == '&') 
        // store the value in the dict and move onto the next element
        # this output is always correct...
        NSLog(@"Key:%@, Value:%@", element, value);
        [self.settingsData setObject:value forKey:element];
        # ...as is this (the value printed above matches the result here)
        NSLog(@"Result:%@", [settingsData objectForKey:element]);
        [value setString:@""];
        [element setString:@""];
        cap_element = true;
    
    # but this will output an empty string (username prints correctly above)
    NSLog(@"%@", [self.settingsData objectForKey@"username"]);

前 2 个 NSLog() cmets 按预期输出,但一旦我离开 for 循环,所有键都保留下来,它们的值变为空字符串(因此输出读取 username = "" 而不是 username = "tester") .如果字典未初始化,我会理解这一点,但我会在上面显示的 init 方法中处理这一点。我错过了什么?

【问题讨论】:

【参考方案1】:

在字典中,您存储的是对“值”和“元素”变量的引用,而不是副本。当您将它们设置为空字符串时:

[value setString:@""];
[element setString:@""];

您也在更新字典中的值。

编辑:要解决,请更改此行:

[self.settingsData setObject:value forKey:element];

为此创建新字符串(stringWithString 应该为您提供自动释放的值):

[self.settingsData setObject: [NSString stringWithString: value] forKey: [NSString stringWithString: element]];

【讨论】:

【参考方案2】:

您在此处将两个字符串的值设置为“”:

[value setString:@""];
[element setString:@""];

NSMutableDictionary 仅具有对原始对象的引用,因此您所做的更改会反映在引用该对象的任何地方。 copy 可变对象很常见,如果你想确保你下面的值不会改变。

【讨论】:

【参考方案3】:

问题出在这里:

[value setString:@""];
[element setString:@""];

在为两者提供字典引用后,您将元素/值设置为空字符串。字典保留了这些引用,而不是它们的值。因此,当您更改元素/值值时,您会意外(至少在这种情况下)更改字典的行为,因为它不再响应您设置的键并且不会返回最初定义的值。

如果您不希望发生这种情况,则需要在重置之前复制字符串。

【讨论】:

以上是关于NSMutableDictionary 实例变量不保留循环外的键值的主要内容,如果未能解决你的问题,请参考以下文章

尽管对象是 NSMutableDictionary,但“发送到不可变对象的变异方法”

NSMutableDictionary 不采用键/值对

iOS 不兼容的指针类型(来自 NSDictionary 的 NSMutableDictionary)

Objective - C NSDictionary不可变字典和NSMutableDictionary可变字典

Foundation框架 - NSDictionary类NSMutableDictionary类

无法更新 NSMutableDictionary?