【问题标题】:Does setObject:forKey: on NSMutableDictionary do an allocation?NSMutableDictionary 上的 setObject:forKey: 是否进行分配?
【发布时间】:2014-03-31 17:36:11
【问题描述】:

假设我有以下内容:

NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];

现在,当我这样做时

[dict setObject:object forKey:key];

是否分配了新的NSMutableDictionaryNSDictionary,其值只是添加到NSMutableDictionary,有点像在Java 中使用String 进行连接?还是只是简单的插入了一个新的键值对?

基本上,我要问的是

说我这样做:

@implementation ....

+(void) initialize 
{
    NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
}

然后做: - (void) addValue { [dict setObject:object forKey:key]; }

这样会更糟还是一样:

- (void) addValue
{
    NSDictionary dict = @[key:object]; 
}    
or 

+ (void) initialize
{
    NSDictionary * dict = @[key:object]; 
}

我知道+initialize 只被调用一次。另外,如果这个类只被调用一次呢?

【问题讨论】:

  • 不,调用setObject:forKey: 只是更新现有的可变字典。为什么会认为创建了一个新字典?
  • 你的初始化方法什么都不做(除了浪费时间),因为blah 是一个局部变量并且不会转义该方法。

标签: ios objective-c cocoa-touch memory-management nsmutabledictionary


【解决方案1】:

要回答您的标题问题,不,setObject 不会分配 NSMutableDictionary。 NSMutableArray 和 addObject 也是如此。要理解为什么,请记住,当对象被定义但未分配时,Objective-C 会将对象设置为 nil。发送到 nil 对象的消息导致 nil,这是一个非常酷的东西,可以用来产生很大的效果。

我认为您要问的另一个问题是关于何时分配 NSMutableDictionary(或任何需要分配的对象)。通常的方法是通过自定义 getter 进行惰性实例化。如果您绝对确定您将使用该对象,则可以将其设置为 init 方法(如上一个示例中所示)。

要查看如何通过自定义 getter 使用惰性实例化,请在 Xcode 中创建一个单视图应用程序(即,文件->新建项目->单视图应用程序等)打开 ViewController.m 文件,并从该属性开始(在界面中):

@property (nonatomic, strong) NSMutableDictionary *mutableDictionary;

这是您的自定义 getter(在实现中):

- (NSMutableDictionary *)mutableDictionary
{
    if(!_mutableDictionary) {
        _mutableDictionary = [[NSMutableDictionary alloc] init];
    }
    return _mutableDictionary;
}

有了这些,你第一次拥有一个

[mutableDictionary setObject:@"myValue" forKey:@"myKey"]

getter 函数将运行 if 块为您分配它。每个后续的 setObject 都将简单地返回现有的可变字典。

【讨论】:

  • 上述模式中的惰性实例化是没有意义的;最好只是在初始化程序中创建字典并完成它。
【解决方案2】:

正如您所说,您来自 Java,这两种语言都有具有不可变(常量)和可变(可修改)数据结构的框架/库,因此您应该熟悉这些概念。你提到了字典和字符串,所以大致对应的是:

  • 不可变字符串:NSString (Cocoa)、String (Java)
  • 可变字符串:NSMutableString (Cocoa)、StringBuffer (Java)
  • 可变字典/映射:NSMutableDictionary (Cocoa)、HashMap (Java)

HTH

【讨论】:

  • 真好。如果有的话,NSDictionary 的对应关系是什么?
  • Java 的 Map 接口支持不可变的实现,但我不知道是否有标准的实现。
【解决方案3】:

不,将对象添加到字典不会导致内存分配。字典保留对您添加的任何对象的强引用,但不会复制或重新分配这些对象。

分配一个可变字典然后向其中添加对象与创建一个固定的非可变字典的区别仅在于您获得了一个可变字典。这可能会分配更多的内存(取决于NSMutableDictionary 是否需要比NSDictionary 更多的内存)。但除非你真的,真的靠墙,记忆明智,否则不值得考虑。

另请注意,虽然+initialize 只被调用一次,但它是一个 方法而不是实例方法。如果你的字典是一个实例属性,你不能在那里创建它。

【讨论】:

  • 将对象添加到字典可能会导致键的内存分配,如果它是可变的。每个条目可能需要分配才能将其链接到表中(不确定他们如何处理)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多