如何制作一个真正的私有实例变量?

51 visibility private objective-c instance-variables

我想创建一个无法从外部访问的实例变量.在objective-c中有可能是这样的吗?我记得Apple有私有变量和类似的东西,但如果人们知道它们,他们就可以使用它们.Apple称之为"私有API",但显然其他人可以访问那些东西,如果他们发现那里有什么.

到目前为止,我认为像这样的东西创建了一个私有实例变量:

@interface MyClass : NSObject {
    CGFloat weight;
}
Run Code Online (Sandbox Code Playgroud)

没有@property,没有@synthesize,只是上面的声明.

另外我知道Apple添加了一个_inFrontOfTheirPrivateInstanceVariables,但他们说某些地方他们不喜欢看到其他人这样做,因为他们可能会在执行此操作时覆盖意外隐藏的实例变量.

这里的诀窍是什么?

Qui*_*lor 60

您可以使用其中的@private关键字{}将所有后续变量声明设为私有.默认可见性是@protected(与protectedJava 类似),通常效果很好.您必须专门声明一个变量,@public因为它可以在类外部直接访问.

Apple文档包含有关可变范围和可见性的更多详细信息.

"私有API"和私有变量之间也存在差异.在Objective-C中,您不能将方法设为私有 - 任何人都可以调用任何方法.有几种方法可以创建"秘密"方法,但这有点超出了这个问题的范围.以下是一些相关的SO问题:

至于变量前面的前导_,请注意Apple还为"私有"方法保留了此前缀.保证避免出现问题的最佳方法是为自己的变量和方法使用常规命名约定.但是,除非你从Cocoa(除了NSObject之外)继承了一些东西,否则你可以相信你不会遇到问题.

  • 他的意思是ObjC的"受保护"就像java的"受保护"一样. (5认同)
  • "有点像Java"不,在Java中,默认访问与"受保护"非常不同 (3认同)

Joh*_*lph 31

使用XCode 4及更高版本中的新LLVM编译器,您可以@private在实现(.m)文件中的默认类别中声明变量:

@interface ClassName()
{
@private
// private variables here
}
@end

@implementation ClassName
// you can use private variables here
@end
Run Code Online (Sandbox Code Playgroud)

我发现这很方便,因为我讨厌污染私有变量带入我的头文件.

  • LLVM GCC不是LLVM编译器,它仍然是GCC,但使用LLVM解析器.我的意思是LLVM 2.0或LLVM 3.0(iOS 5 Beta,XCode 4.2). (3认同)
  • 嗨约翰内斯,应该删除@private指令后的冒号...... (3认同)

ste*_*tef 9

您可以通过仅在@implementation中使用它们来定义私有方法,而不是@interface.

类似地,您可以在@implementation开始时在匿名块内定义私有实例变量 - 就像在@interface中对公共ivars所做的那样.

请参阅以下示例.

@interface EXClass : NSObject
{
uint8_t publicInteger;
float publicFloat;
}

-(void)publicMethod;
@end

@implementation EXClass
{
uint8_t privateInteger;
float privatefloat;
}

-(BOOL)privateMethod {
return FALSE;
}
Run Code Online (Sandbox Code Playgroud)

请记住,objective-C方法在运行时作为消息发送(而不是C++的编译时绑定),因此respondsToSelector:仍将返回true并且performSelector:仍将调用该方法.伊娃将是完全私人的.

但是,如果你正在创建一个库,理论上没有人会知道你没有在头文件中声明的任何方法.