objective-c 如何制作真正的私有实例变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1262463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 22:03:21  来源:igfitidea点击:

How to make a real private instance variable?

objective-cprivatevisibilityinstance-variables

提问by Quinn Taylor

I want to make an instance variable that can't be accessed from outside. Is something like that possible in objective-c? I remember Apple has private variables and stuff like that, but if people know about them, they can use them. Apple calls that "private API", but obviously others can access that stuff if they find out what's in there.

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

Until now I believed that something like this creates a private instance variable:

直到现在我相信这样的事情会创建一个私有实例变量:

@interface MyClass : NSObject {
    CGFloat weight;
}

No @property, no @synthesize, just the declaration above.

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

Also I know Apple adds a _inFrontOfTheirPrivateInstanceVariables, but they said somewhere that they don't like to see others doing that because they might override accidently hidden instance variables when doing that.

我也知道 Apple 添加了一个 _inFrontOfTheirPrivateInstanceVariables,但他们在某处说他们不喜欢看到其他人这样做,因为他们在这样做时可能会覆盖意外隐藏的实例变量。

What's the trick here?

这里有什么诀窍?

回答by Quinn Taylor

You can use the @privatekeyword inside the {}to make all subsequent variable declarations private. The default visibility is @protected(which is similar to protectedin Java) and that generally works well. You'd have to specifically declare a variable as @publicfor it to be directly accessible outside the class.

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

This Apple documentationhas further details about variable scope and visibility.

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

There is also a difference between "private API" and private variables. In Objective-C, you cannot make methods private — anyone can call any method. There are several ways to create "secret" methods, but that's somewhat out of the scope of this question. Here are a few related SO questions:

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

As far as the leading _ in front of variables, be aware that Apple also reserves this prefix for "private" methods. The best way to guarantee you avoid problems is to use normal naming conventions for your own variables and methods. However, unless you subclass something from Cocoa (other than NSObject) you can be fairly confident that you won't run into problems.

至于变量前面的前导 _,请注意 Apple 也为“私有”方法保留了这个前缀。保证您避免问题的最佳方法是为您自己的变量和方法使用正常的命名约定。然而,除非你从 Cocoa 继承某些东西(NSObject 除外),否则你可以相当有信心不会遇到问题。

回答by Johannes Rudolph

With the new LLVM Compiler available in XCode 4 and later, you can declare @privatevariables in default categories inside your implementation (.m) file:

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

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

@implementation ClassName
// you can use private variables here
@end

I find this convenient, as I hate the pollution private variables bring into my header files.

我觉得这很方便,因为我讨厌私有变量带入我的头文件的污染。

回答by stef

You can define private methods by simply having them only in the @implementation, and not the @interface.

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

Similarly, you can define private instance variables inside an anonymous block at the start of the @implementation - as you do for public ivars inside the @interface.

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

See the following example.

请参阅以下示例。

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

-(void)publicMethod;
@end

@implementation EXClass
{
uint8_t privateInteger;
float privatefloat;
}

-(BOOL)privateMethod {
return FALSE;
}

Remember that objective-C methods are sent as messages at runtime, though (rather than C++'s compile time binding), so respondsToSelector: would still return true and performSelector: would still call the method. The ivars would be fully private.

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

If you were making a library, though, theoretically no one would know about any methods you didn't declare in the header files.

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

回答by kubi

All iVars in Objective-C are protected by default. If you don't write the accessor methods than other classes won't be able to see the variables.

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

The two exceptions are categories and subclasses.

两个例外是类别和子类。

回答by criscokid

The Apple docs for naming instance variables doesn't explicit warn against using underscore in the name of instance variables like the private method documents do.

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

Naming Instance Variables and Data Types

命名实例变量和数据类型

I also remember a conversation between Wil Shipley and a few other OS X developers concern the underscores. Because of the way the Obj-C compiler works, if Apple were to add a new instance variable to a class in their frameworks, it would cause all apps using those frameworks to need to be recompiled. As far as pre-existing instance variables, you should get a warning when you step on one.

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

回答by Ege Akpinar

I saw the following usage in a sample app (PaintGL) by Apple

我在 Apple 的示例应用程序 (PaintGL) 中看到了以下用法

In .m file

在 .m 文件中

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

Disclaimer: The sample app only has method declarations, I saw the private property declaration in this SO thread

免责声明:示例应用程序只有方法声明,我在这个 SO 线程中看到了私有属性声明

回答by Binarian

You can notmake a real private instance variable. Objective-C is a dynamic language and therefore it is possible to access any variable (even @private).

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

My best approach:

我最好的方法:

Use it in the implementation block of you .m file. Then it is not visible and block KVC, so that KVC will not work

在 .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