Objective c 为目标C中的实例变量赋值

Objective c 为目标C中的实例变量赋值,objective-c,instance-variables,Objective C,Instance Variables,我看到的函数是: -(void)viewDidLoad { NSBundle *bundle = [NSBundle mainBundle]; NSString *plistPath = [bundle pathForResource:@"statedictionary" ofType:@"plist"]; NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath]

我看到的函数是:

-(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:)];

stateships
属性可能被保留,这就是原因

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

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

self.statesZips = [NSDictionary dictionaryWithContentsOfFile:plistPath];
因为
dictionaryWithContentsOfFile
返回一个自动删除的对象

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

我建议你阅读这篇文章以了解更多信息


编辑:当我第一次阅读您的问题时,我一定错过了最后一部分,但Barry已经回答了该部分。

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

self.statesZips = [[[NSDictionary alloc] initWithContentsOfFile:plistPath] autorelease];
但代价是不太明确的内存管理(依靠
NSAutoreleasePool
在事件循环迭代结束时释放alloc'd实例)

电话

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

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

似乎没有人解决以下事实:

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

前一行:

[[NSDictionary alloc] initWithContentsOfFile:plistPath];
分配一个对象。这使您有责任在不再需要它时释放它。将它分配给
stateszip
属性后,它不再需要,因此它被释放,您不应该再使用
dictionary
。您会注意到,以后的代码只引用
self.stateZips
,not
字典

在方法后面的
NSArray
中,
viewDidLoad
不分配对象,因此该方法不负责对其调用
release
。经验法则是,如果
alloc
it,则负责确保它被释放。否则,这不是您的问题


数组排序使用
sortedArrayingSelector:
方法。选择器识别Objective-C中的方法。
@selector
是选择器的文本语法(有点像
@“
NSString
对象的文本语法)。因此,该代码所说的是"给我一个数组,在数组中对
组件中的对象进行排序,并在排序时使用
比较:
方法对每个对象进行比较。当它对数组进行排序时,它将调用数组中的对象上的
比较:
,以确定如何对它们进行排序。

我实际上认为ATESJIPS属性是不相关的。代码分配一个对象,因此需要释放它,而不管StateSJIPS的语义如何,除非它在垃圾收集环境中运行。@Barry Wark:不,StateSJIPS的语义非常相关。如果该方法不保留字典或复制它,请在li之后访问StateSJIPne 7将导致未定义的行为(可能是segfault)。诸如initWithContentsOfFile之类的便利函数会自动删除。这是不正确的。初始化器(如
initWithContentsOfFile:
)返回未自动删除的对象。诸如
dictionaryWithContentsOfFile:
之类的方便方法会自动删除。+1表示对所问问题的实际正确答案。statesZip属性的语义在此处不相关。此模式的原因是您描述的代码易读性和显式内存管理。感谢苹果公司的ARC,这样我们今后的问题会越来越少(我想访问块变量问题是新的保留/发布问题)