Objective c 如何生成真正的私有实例变量?

Objective c 如何生成真正的私有实例变量?,objective-c,private,visibility,instance-variables,Objective C,Private,Visibility,Instance Variables,我想创建一个无法从外部访问的实例变量。在objective-c中可能有这样的情况吗?我记得苹果有私有变量之类的东西,但如果人们知道它们,他们可以使用它们。苹果称之为“私有API”,但很明显,如果其他人发现里面有什么,他们可以访问这些东西 到目前为止,我相信类似这样的东西会创建一个私有实例变量: @interface MyClass : NSObject { CGFloat weight; } 没有@property,没有@synthesis,只有上面的声明 我还知道苹果公司在Priva

我想创建一个无法从外部访问的实例变量。在objective-c中可能有这样的情况吗?我记得苹果有私有变量之类的东西,但如果人们知道它们,他们可以使用它们。苹果称之为“私有API”,但很明显,如果其他人发现里面有什么,他们可以访问这些东西

到目前为止,我相信类似这样的东西会创建一个私有实例变量:

@interface MyClass : NSObject {
    CGFloat weight;
}
没有@property,没有@synthesis,只有上面的声明

我还知道苹果公司在PrivateInstanceVariables上添加了一个_infonto,但他们在某个地方说,他们不喜欢看到其他人这样做,因为这样做时可能会覆盖意外隐藏的实例变量


这里有什么诀窍?

您可以在
{}
中使用
@private
关键字将所有后续变量声明设置为私有。默认的可见性是
@protected
(类似于Java中的
protected
),通常效果良好。您必须将变量明确声明为
@public
,以便在类外直接访问它

有关于变量范围和可见性的更多详细信息

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


至于变量前面的前导uuu,请注意苹果也为“私有”方法保留了这个前缀。保证避免出现问题的最佳方法是对自己的变量和方法使用常规命名约定。但是,除非您从Cocoa(而不是NSObject)中对某个对象进行子类化,否则您可以确信不会遇到问题。

默认情况下,Objective-C中的所有IVAR都受到保护。如果不编写访问器方法,其他类将无法看到变量


这两个例外是类别和子类。

用于命名实例变量的Apple文档没有像私有方法文档那样明确警告不要在实例变量的名称中使用下划线


我还记得Wil Shipley和其他几个OS X开发人员之间的一次对话,讨论的是下划线。由于Obj-C编译器的工作方式,如果苹果向其框架中的类添加一个新实例变量,将导致所有使用这些框架的应用程序都需要重新编译。对于预先存在的实例变量,当您使用一个实例变量时,应该会收到警告。

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


我觉得这样做很方便,因为我讨厌私有变量引入头文件。

您可以定义私有方法,只需将它们放在@implementation中,而不放在@interface中即可

类似地,您可以在@implementation开始时在匿名块中定义私有实例变量,就像在@interface中定义公共IVAR一样

请参见下面的示例

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

-(void)publicMethod;
@end

@implementation EXClass
{
uint8_t privateInteger;
float privatefloat;
}

-(BOOL)privateMethod {
return FALSE;
}
请记住,objective-C方法在运行时作为消息发送(而不是C++的编译时绑定),因此respondsToSelector:仍将返回true,而performSelector:仍将调用该方法。IVAR将完全保密


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

我在苹果的一个示例应用程序(PaintGL)中看到了以下用法

在.m文件中

@interface MyClass (private)
  - (void) privateMethod();
  @property(...) myProperty;
@end

免责声明:示例应用程序只有方法声明,我看到私有属性声明

您可以创建真正的私有实例变量。Objective-C是一种动态语言,因此可以访问任何变量(甚至@private)

我的最佳方法: 在you.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

他们将能够通过valueForKey:和setValue:forKey:与他们互动。但是,我不知道KVC是这样工作的,谢谢你的发帖。事实证明,您可以通过直接重写
+(BOOL)accessInstanceVariables
来关闭此行为。Objective-C现在允许在不影响子类的情况下将IVAR添加到类中(使用Leopard和iPhone OS 2.0附带的2.0语言更新)“类似于Java中的”不,在Java中,默认访问与“protected”非常不同,他指的是ObjC的“protected”与java的“protected”一样。很抱歉,我稍微澄清了我的答案。您是对的,Java的“默认”访问与“受保护”访问非常不同。我不是想把两者混为一谈。@QuinnTaylor对,默认的包保护可见性不应该应用于Objective-C,因为没有包。这不适用于针对iOS 4.2的LLVM GCC 4.2和Xcode 4.0.2。你的意思是“LLVM 2.0编译器”?LLVM GCC不是LLVM编译器,它仍然是GCC,但带有LLVM解析器。我指的是LLVM2.0或LLVM3.0(iOS5beta,XCode 4.2)。啊,很抱歉。不过,注意这一点可能很重要,尤其是对于与其他人一起处理项目的人来说,只使用这一个编译器。您可以使用
@protocol
对客户端“隐藏”您的实例变量。@RaffiKhatchadourian这不是
@protocol
的目的。也无助于在课堂上隐藏ivar。它只是隐藏了整个班级。如果你想提供答案,你应该自己做答案输入。“理论上,没有人会知道你没有在头文件中声明的任何方法。”-不是这样。我已经能够写一个相当有侵入性的Xcode插件,尽管苹果的la
@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