Properties and Instance Variables in Objective-C
我对Objective-C中的属性和实例变量相当困惑。
我大概已经完成了Aaron Hillegas的"MacOSX的可可编程",一切都是合乎逻辑的。您将声明这样的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 | @class Something; @interface MyClass : NSObject { NSString *name; NSArray *items; Something *something; IBOutlet NSTextField *myTextField; } @property (nonatomic, retain) NSString *name; @property (nonatomic, retain) NSArray *items; |
由于其他对象需要操纵我们的
name 和items 实例变量,所以我们使用@property 和@synthesize 为它们生成访问器/变异器。在我们的类中,我们不使用只与实例变量直接交互的访问器/转换器。something 只是我们将在类中使用的一个实例变量,由于没有其他人需要使用它,因此我们不会为它创建一对访问器和赋值器。我们需要与UI中的文本字段交互,因此我们为它声明一个
IBOutlet ,连接它,然后我们就完成了。
一切都很合乎逻辑。
然而,在iPhone世界里,情况似乎有所不同。人们为每个实例变量声明属性,为
为什么?怎么回事?这些差异是iPhone特有的吗?为所有实例变量声明属性、为
在iPhone世界里,没有垃圾收集器。你必须通过引用计数来小心地管理内存。考虑到这一点,考虑以下两者之间的区别:
1 | name = @"Test"; |
和
1 2 3 | self.name = @"Test"; // which is equivalent to: [self setName: @"Test"]; |
如果直接设置实例变量,而不事先考虑,则会丢失对前一个值的引用,并且无法调整其保留计数(您应该手动使用
基本概念不是针对iPhone的,但在没有垃圾收集器的环境中,它变得至关重要。
属性用于为实例变量生成访问器,不会发生任何魔力。
您可以手动实现相同的访问器。
你可以在Aaron Hillegass的书中找到成员变量的3种记忆管理策略的例子。他们是
我假设你理解客观C中的记忆管理…
访问器隐藏每个变量的内存管理的复杂性和差异。
例如:
1 | name = @"Test" |
这是一个简单的任务,
1 2 | [self setName:@"Test"] [self name] |
现在,
我的猜测是,iPhone教程使用属性使新开发人员更容易跳过内存管理(即使用属性生成适当的访问器,而不是每次都手工实现这些访问器也很方便)。
However, in the iPhone world, things seem to be different. People declare properties for every single instance variable, declare properties for
IBOutlets , and use accessors/mutators to interact with instance variables within the class (e.g. they would write[self setName:@"Test"] rather thanname = @"Test" ).
这不是iPhone特有的。除
人们"为每个实例变量声明属性"的原因很可能是他们的所有实例变量都是他们希望作为属性公开的东西。如果他们有一些想要保密的东西,他们不会在头文件中声明它的属性。(但是,他们可以在实现文件的类扩展名中为其创建一个属性,以便获得上述的免费KVO通知。)
在我看来,为销售点申报房产是多余的。我看不出有什么意义。如果不创建属性,NIB加载器将通过直接实例变量访问来设置出口,这对于该任务来说很好。
我建议,现代发展已经作出了非常强烈的尝试,以确定、定义和应用最佳实践。
在这些最佳实践中,我们发现了连续性和一致性。
除了争论在
你可以这样写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //MyClass.h @class Something; @interface MyClass : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSArray *items; @end //MyClass.m @interface MyClass() @property (nonatomic, strong) IBOutlet NSTextField *myTextField; @property (nonatomic, strong) Something *something; @end |