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,这样我们今后的问题会越来越少(我想访问块变量问题是新的保留/发布问题)