如何做一个真正的私人实例variables?
我想创build一个不能从外部访问的实例variables。 在objective-c中有这样的可能吗? 我记得苹果有私人变数和类似的东西,但如果人们知道他们,他们可以使用它们。 苹果称之为“私人API”,但显然其他人可以访问那些东西,如果他们发现那里的东西。
直到现在我相信像这样的东西创build一个私人实例variables:
@interface MyClass : NSObject { CGFloat weight; }
没有@property,没有@synthesize,只是上面的声明。
另外我知道苹果增加了一个_inFrontOfTheirPrivateInstanceVariables,但他们说某处他们不喜欢看到其他人这样做,因为他们可能会覆盖意外隐藏的实例variables。
这里有什么窍门?
您可以在{}
内使用@private
关键字来使所有后续variables声明为私有。 默认的可见性是@protected
(类似于Java中的protected
),通常效果很好。 您必须特别声明一个variables作为@public
才能在课程外面直接访问。
这个苹果文档有关variables范围和可见性的更多细节。
“私有API”和私有variables也有区别。 在Objective-C中,你不能使方法保密 – 任何人都可以调用任何方法。 有几种方法可以创build“秘密”方法,但是这个问题有些超出了这个问题的范围。 这里有几个相关的SO问题:
- 关于Objective-C中的私有实例variables
- Objective-C中“@private”是什么意思?
- 是否有可能在Objective-C中声明一个私有的方法?
- 在Objective-C中为类定义私有方法的最佳方法
就前面的variables而言,请注意苹果公司也为“私人”方法保留了这个前缀。 保证您避免问题的最佳方法是对您自己的variables和方法使用正常的命名约定。 但是,除非你从Cocoa(NSObject除外)inheritance了某些东西,否则你可以相当自信地认为你不会遇到问题。
使用XCode 4及更高版本中提供的新LLVM编译器,您可以在实现(.m)文件中的默认类别中声明@private
variables:
@interface ClassName() { @private // private variables here } @end @implementation ClassName // you can use private variables here @end
我觉得这很方便,因为我讨厌污染私人variables带入我的头文件。
您可以通过仅在@implementation中定义私有方法,而不是@interface。
同样,你可以在@implementation开始的时候在一个匿名块中定义私有实例variables – 就像你在@interface里面的公有ivars一样。
看下面的例子。
@interface EXClass : NSObject { uint8_t publicInteger; float publicFloat; } -(void)publicMethod; @end @implementation EXClass { uint8_t privateInteger; float privatefloat; } -(BOOL)privateMethod { return FALSE; }
请记住,虽然(而不是C ++的编译时绑定)Objective-C方法作为消息在运行时发送,所以respondsToSelector:仍然会返回true,而performSelector:仍然会调用方法。 艾瓦斯将是完全私人的。
如果你正在创build一个库,理论上没有人会知道你没有在头文件中声明的任何方法。
Objective-C中的所有iVar都是默认保护的。 如果你不写其他的类,将无法看到variables。
两个例外是类别和子类别。
用于命名实例variables的Apple文档没有明确地警告在私有方法文档的实例variables的名称中使用下划线。
命名实例variables和数据types
我还记得Wil Shipley和其他一些OS X开发人员之间的交谈关于下划线。 由于Obj-C编译器的工作方式,如果苹果在其框架中为一个类添加一个新的实例variables,将会导致所有使用这些框架的应用程序需要重新编译。 就已有的实例variables而言,当你踩一个variables时,你应该会得到一个警告。
我在Apple的示例应用程序(PaintGL)中看到了以下用法
在.m文件中
@interface MyClass (private) - (void) privateMethod(); @property(...) myProperty; @end
免责声明:示例应用程序只有方法声明,我看到在这个SO线程私有财产声明
你不能做一个真正的私人实例variables。 Objective-C是一种dynamic语言,因此可以访问任何variables(甚至是@private)。
我最好的办法:
在你的.m文件的实现块中使用它。 那么它是不可见的,并阻止KVC,所以KVC将无法正常工作
@implementation ClassName { // default to @protected // but the subclasses can't see ivars created in the implementation block float number; } + (BOOL)accessInstanceVariablesDirectly { return NO; // no KVC } @end