首先,您没有声明变量;你在声明一个属性。属性由实例变量支持,但它也添加方法。以下是变量放置位置的说明:
@interface MyClass : NSObject {
NSInteger i ;
}
@end
这是一个在你的类上放置实例变量的地方。它只能通过您的类和类别的方法访问。 (旁注:它可以被外部访问,但这不是推荐的做法)
另一个例子:
@interface MyClass : NSObject
@end
@implementation MyClass {
NSInteger i ;
}
@end
这也是一个实例变量,但只能通过该块内编写的方法访问。 (旁注:可以通过挖掘类定义来访问它,但这不是推荐(或常见)的做法)
另一个例子:
@interface MyClass : NSObject
@property NSInteger i ;
@end
等同于:
@interface MyClass : NSObject {
NSInteger _i ; // you are not allowed to access it by this variable
}
- (NSInteger) i ;
- (void) setI:(NSInteger)value ;
@end
这是人们可以获取和设置的属性。您在方法或其他方法中使用该变量:
NSLog ( @"The value is %i" , self.i ) ; // if it's your instance method
NSLog ( @"The value is %i" , object.i ) ; // if it's object's instance method
另一个例子:
@interface MyClass : NSObject {
NSInteger i ;
}
@property NSInteger i ;
@end
@implementation MyClass
@synthesize i ; // Causes the property to line up with the ivar by the same name.
@end
等同于:
@interface MyClass : NSObject {
NSInteger i ; // you ARE allowed to use this since you defined it
}
- (NSInteger) i ;
- (void) setI:(NSInteger)value ;
@end
在这里,您可以使用 getter/setter 方法或实例变量本身。但是,您通常应该使用这些方法,因为您 [隐式] 将它们声明为原子的,因此它们具有线程同步。如果你想让它不做线程(并加快它,只要你不打算在多线程环境中使用它):
@property (nonatomic) NSInteger i ;
@property (nonatomic,readonly) NSInteger i ; // only makes a getter method
我建议暂时避免这种情况并使用直接属性,因为它可以帮助您避免很多常见错误。除非您分析您的程序并确定这是导致性能损失的原因,否则您可能应该简单地使用这些属性。
另一个例子:
@interface MyClass : NSObject
@end
@implementation MyClass
NSInteger i ;
@end
这不是实例变量。它是一个全局变量,恰好写在您的 @implementation 范围内。
如何将其转换为实例变量,请参见上文(即放在大括号中)。
还有一点:
像这样声明一个属性:
@interface MyClass ()
@property NSInteger i ;
@end
不会将其设为私有。但是,它隐藏在人们通常无法访问的文件中,因此编译器不知道属性存在。
代码中其他地方的其他函数仍然可以调用:
[yourObject i] ;
要获取该属性的值 - 但他们必须先知道它的存在。
在 cmets 中回答问题的附录:
默认情况下,属性是原子的。它不一定遵循原子的严格定义(这是一罐蠕虫我建议你现在不要看),但具有相同的效果:线程保证看到一个完整的和向上的-to-date 值,无论何时另一个线程写入它。它通常在合成 getter/setter 方法时这样做:
- (NSInteger) i {
@synchronized(self) {
return i ;
}
}
- (void) setI:(NSInteger)value {
@synchronized(self) {
i = value ;
}
}
如果您改为指定nonatomic,它将合成这些:
- (NSInteger) i {
return i ;
}
- (void) setI:(NSInteger)value {
i = value ;
}
如果您的属性是 atomic,那么您永远不应该直接访问 ivar。这样做违反了您一开始就提供的线程保护。 (旁注:在某些情况下您可以,但请等到您对线程/同步更加熟悉后再尝试。)