2

我正在查看的功能:

-(void)viewDidLoad {
    NSBundle *bundle = [NSBundle mainBundle];
    NSString *plistPath = [bundle pathForResource:@"statedictionary" ofType:@"plist"];

    NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
    self.statesZips = dictionary;
    [dictionary release];

    NSArray *components = [self.stateZips allKeys];
    NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)];
    self.States = sorted;

    NSString *selectedState = [self.states objectAtIndex:0];
    NSArray *array = [stateZips objectForKey: selectedState];
    self.zips = array;  
}

为什么先分配一个NSDictionary,然后分配给一个叫*dictionary的指针,再分配给实例变量stateZips?为什么不分配它并将其直接分配给实例变量并节省创建和释放另一个 NSDictionary 的内存?始终遵循相同的方法,包括稍后在此函数中使用 NSArray...

NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
self.statesZips = dictionary;
[dictionary release];

此外,这种排序将哈希表(字典)中的键按字母顺序排列。我不确定我是否理解这一行:

NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)];
4

3 回答 3

6

似乎没有人解决这一事实,即这条线

self.statesZips = dictionary;

不是直接的实例变量赋值。stateZips是一个属性,因此该行代码调用该setStateZips:方法。该方法保留或复制字典,因此除非该viewDidLoad方法打算出于某种目的再次使用它,否则不再需要它。这样就可以release了。

上一行:

[[NSDictionary alloc] initWithContentsOfFile:plistPath];

分配一个对象。release一旦您不再需要它,这就是您对它的责任。将其分配给statesZips属性后,不再需要它,因此已释放,您不应再使用dictionary。你会注意到后面的代码只引用了self.stateZips,而不是dictionary.

NSArray在方法后面的情况下,viewDidLoad不分配对象,所以该方法不负责调用release它。经验法则是,如果你alloc这样做,你有责任确保它被释放。否则,这不是你的问题。

使用该sortedArrayUsingSelector:方法对数组进行排序。选择器标识了 Objective-C 中的方法。这@selector是选择器的文字语法(有点像对象@""的文字语法NSString)。因此,该代码所说的是“给我一个数组,其中的对象components已排序,并在您进行排序时使用该compare:方法比较每个对象。当它对数组进行排序时,它将调用compare:数组中的对象以确定如何将它们按顺序排列。

于 2009-03-25T21:47:10.183 回答
4

statesZips属性可能被保留,这就是推理。

第一次分配 NSDictionary 时,它的保留计数为 1。当它分配给 statesZips 时,保留计数变为 2。当它被释放时,保留计数下降到 1,这通常是期望的结果。

请注意,下面的代码会产生(几乎)相同的结果:

self.statesZips = [NSDictionary dictionaryWithContentsOfFile:plistPath];

因为dictionaryWithContentsOfFile返回一个自动释放的对象。

按照惯例,类方法如[NSDictionary dictionary]返回 autoreleased 对象(一段时间后会自动释放),而通常的 alloc-init 方法(如[[NSDictionary alloc] init])返回保留对象。

我建议您阅读Cocoa 的内存管理编程指南以获取更多信息。

编辑:当我第一次阅读它时,我一定错过了你问题的最后一部分,但巴里已经回答了那部分。

于 2009-03-25T21:03:04.877 回答
2

此代码使用引用计数内存管理(不是 OS X 上的 Objective-C 2.0 中可用的自动垃圾回收内存管理)。当任何对象(在本例中为 NSDictionary 和 NSArray)被分配时,调用者负责调用-release该实例。调用 release 失败会导致内存泄漏。代码可以写成

self.statesZips = [[[NSDictionary alloc] initWithContentsOfFile:plistPath] autorelease];

但是以较少显式的内存管理为代价(依赖于NSAutoreleasePool在事件循环迭代结束时释放分配的实例。

通话

[components sortedArrayUsingSelector:@selector(compare:)];

返回一个数组,其元素来自,components但根据调用 [elem1 compare:elem2] 的返回值比较两个数组元素。

于 2009-03-25T21:03:22.100 回答