这是在 Objective-C 中声明的各种变量的示例。变量名表明它的访问。
文件:Animal.h
@interface Animal : NSObject
{
NSObject *iProtected;
@package
NSObject *iPackage;
@private
NSObject *iPrivate;
@protected
NSObject *iProtected2; // default access. Only visible to subclasses.
@public
NSObject *iPublic;
}
@property (nonatomic,strong) NSObject *iPublic2;
@end
文件:Animal.m
#import "Animal.h"
// Same behaviour for categories (x) than for class extensions ().
@interface Animal(){
@public
NSString *iNotVisible;
}
@property (nonatomic,strong) NSObject *iNotVisible2;
@end
@implementation Animal {
@public
NSString *iNotVisible3;
}
-(id) init {
self = [super init];
if (self){
iProtected = @"iProtected";
iPackage = @"iPackage";
iPrivate = @"iPrivate";
iProtected2 = @"iProtected2";
iPublic = @"iPublic";
_iPublic2 = @"iPublic2";
iNotVisible = @"iNotVisible";
_iNotVisible2 = @"iNotVisible2";
iNotVisible3 = @"iNotVisible3";
}
return self;
}
@end
请注意,iNotVisible 变量在任何其他类中都不可见。这是一个可见性问题,因此用@property
或@public
不改变它来声明它们。
@property
在构造函数中,最好使用下划线访问声明的变量self
以避免副作用。
让我们尝试访问变量。
文件:Cow.h
#import "Animal.h"
@interface Cow : Animal
@end
文件:Cow.m
#import "Cow.h"
#include <objc/runtime.h>
@implementation Cow
-(id)init {
self=[super init];
if (self){
iProtected = @"iProtected";
iPackage = @"iPackage";
//iPrivate = @"iPrivate"; // compiler error: variable is private
iProtected2 = @"iProtected2";
iPublic = @"iPublic";
self.iPublic2 = @"iPublic2"; // using self because the backing ivar is private
//iNotVisible = @"iNotVisible"; // compiler error: undeclared identifier
//_iNotVisible2 = @"iNotVisible2"; // compiler error: undeclared identifier
//iNotVisible3 = @"iNotVisible3"; // compiler error: undeclared identifier
}
return self;
}
@end
我们仍然可以使用运行时访问不可见的变量。
文件:Cow.m(第 2 部分)
@implementation Cow(blindAcess)
- (void) setIvar:(NSString*)name value:(id)value {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
object_setIvar(self, ivar, value);
}
- (id) getIvar:(NSString*)name {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
id thing = object_getIvar(self, ivar);
return thing;
}
-(void) blindAccess {
[self setIvar:@"iNotVisible" value:@"iMadeVisible"];
[self setIvar:@"_iNotVisible2" value:@"iMadeVisible2"];
[self setIvar:@"iNotVisible3" value:@"iMadeVisible3"];
NSLog(@"\n%@ \n%@ \n%@",
[self getIvar:@"iNotVisible"],
[self getIvar:@"_iNotVisible2"],
[self getIvar:@"iNotVisible3"]);
}
@end
让我们尝试访问不可见的变量。
文件:main.m
#import "Cow.h"
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
@autoreleasepool {
Cow *cow = [Cow new];
[cow performSelector:@selector(blindAccess)];
}
}
这打印
iMadeVisible
iMadeVisible2
iMadeVisible3
请注意,我能够访问_iNotVisible2
子类私有的支持 ivar。在 Objective-C 中,所有变量都可以被读取或设置,即使是那些被标记的@private
,也不例外。
我没有包括关联对象或 C 变量,因为它们是不同的鸟。至于 C 变量,任何定义在外部的变量,@interface X{}
或者@implementation X{}
是具有文件范围和静态存储的 C 变量。
I didn't discuss memory management attributes, or readonly/readwrite, getter/setter attributes.