如何做一个真正的私人实例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)文件中的默认类别中声明@privatevariables:

 @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