xcode 如何声明在类实例之外不可见或不可用的实例变量和方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5826345/
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
How to declare instance variables and methods not visible or usable outside of the class instance?
提问by martin's
I've looked through a bunch of posts on this subject. Maybe I didn't run across "the one" and someone will point me in that direction. The question is simple and probably has a simple answer.
我浏览了一堆关于这个主题的帖子。也许我没有遇到“那个”,有人会指向那个方向。这个问题很简单,可能有一个简单的答案。
If you have two ivars, say, "public_ivar" and "private_ivar", where/how should you declare them so that what is public is public and what is private is not exposed in any way to anyone looking at the header file?
如果你有两个 ivar,比如说“public_ivar”和“private_ivar”,你应该在哪里/如何声明它们,以便什么是公共的,什么是公共的,什么是私有的,不会以任何方式暴露给任何查看头文件的人?
Same question in the case of "public_method" and "private_method".
在“public_method”和“private_method”的情况下同样的问题。
I like clean header files (in other languages) that only expose the methods and ivars I want someone else to see. You should be able to publish your header file and not run into the danger of someone accessing something they are not supposed to. How do you do that in objective-C.
我喜欢干净的头文件(其他语言),它只公开我想让其他人看到的方法和变量。您应该能够发布您的头文件,并且不会遇到有人访问他们不应该访问的内容的危险。你如何在 Objective-C 中做到这一点。
For example, let's say that I decide that I need to use an ivar to keep track of some data, a counter or somthing like that, between various class methods that all need access to this information. If that ivar is declared conventionally in the header under @interface its existence is publicly advertised and it is usable by anyone creating an instance of the class. The ideal scenario would be that this ivar would not be visible at all outside of the class implementation.
例如,假设我决定我需要使用 ivar 来跟踪一些数据、计数器或类似的东西,在所有需要访问此信息的各种类方法之间。如果在@interface 下的标头中按惯例声明了该 ivar,则它的存在将被公开宣传,并且任何创建该类实例的人都可以使用它。理想的情况是这个 ivar 在类实现之外根本不可见。
回答by
You can declare instance variables or declared properties in a class extension. Since a class extension is declared in an implementation file (i.e., not a header file), they won't be visible to someone inspecting the header file. For instance, in the header file:
您可以在类扩展中声明实例变量或声明的属性。由于类扩展是在实现文件(即,不是头文件)中声明的,因此检查头文件的人将看不到它们。例如,在头文件中:
@interface SomeClass : NSObject
@end
and in the implementation file:
并在实现文件中:
@interface SomeClass ()
@property (nonatomic, assign) int privateInt;
@end
@implementation SomeClass
@synthesize privateInt;
…
@end
or
或者
@interface SomeClass () {
int privateInt;
}
@end
@implementation SomeClass
…
@end
Note that there's nothing preventing access to private/class extension instance variables (or the accessor methods for properties declared in a class extension) during runtime. I've written a rather detailed post about this as an answer to another question on Stack Overflow: Does a private @property create an @private instance variable?
请注意,在运行时没有任何内容阻止访问私有/类扩展实例变量(或类扩展中声明的属性的访问器方法)。我写了一篇关于这个的相当详细的帖子作为对堆栈溢出另一个问题的回答:Does a private @property create an @private instance variable?
Edit:Instance variables in class extensions were presented in WWDC 2010 session 144.
编辑:类扩展中的实例变量在 WWDC 2010 session 144 中介绍。
Edit:"Using the Clang/LLVM 2.0 compiler, you can also declare properties and instance variables in a class extension."
编辑:“使用 Clang/LLVM 2.0 编译器,您还可以在类扩展中声明属性和实例变量。”
回答by ughoavgfhw
Use class extensionsto add to a class in your implementation file. A class extension is basically an unnamed category with a few bonuses: properties declared in it can be synthesized and anything declared in it must be in the main implementation, so the compiler can check to make sure you didn't miss an implementation. You must put the class extension before your implementation. You can't add instance variables directly in a class extension, but you can add properties. When you synthesize accessors for properties which don't have corresponding instance variables, the new runtime (os x 10.5 and later and all versions of iOS, I believe) will create the instance variables automatically. This means you can't create your own accessors, however, unless you put the instance variable in your header. Private methods can be added to the class extension without restriction, but as Anomie noted, it is technically possible to use them if you know what they are called, and with class-dump, nothing is safe.
使用类扩展添加到实现文件中的类。类扩展基本上是一个未命名的类别,有一些好处:在其中声明的属性可以合成,并且在其中声明的任何内容都必须在主实现中,因此编译器可以检查以确保您没有错过任何实现。您必须在实现之前放置类扩展。您不能直接在类扩展中添加实例变量,但可以添加属性。当您为没有相应实例变量的属性合成访问器时,新的运行时(我相信 os x 10.5 和更高版本以及所有版本的 iOS)将自动创建实例变量。这意味着您无法创建自己的访问器,除非您将实例变量放在标题中。
Example usage of a class extension:
类扩展的示例用法:
@interface MyClass ()
@property (retain) id privateIvar;
@property (readwrite) id readonlyProperty; // bonus! class extensions can be used to make a property that is publicly readonly and privately readwrite
- (void)privateMethod;
@end
@implementation MyClass
@synthesize privateIvar; // the runtime will create the actual ivar, and we just access it through the property
- (void)privateMethod {
...
}
...
Another way of creating "instance variables" without putting them in the header or using a property is to use associative references, which add data to an object at runtime. They aren't technically the same as instance variables, and the syntax for them is more complex. Since they also require the new runtime, there are only two reasons you would ever really want to use them: you want to add an instance variable in a category (outside the scope of this question) or you need it to be really reallyprivate. An associative reference doesn't create any methods or add to the class's definition in the compiled code, so if you don't create wrappers for them it is impossible to find out about them without asking the object after you add the data. See the bottom of the page I linked for a complete usage example.
另一种创建“实例变量”而不将它们放在标题中或使用属性的方法是使用关联引用,它在运行时向对象添加数据。它们在技术上与实例变量不同,它们的语法更复杂。由于它们还需要新的运行时,因此您真正想要使用它们的原因只有两个:您想要在类别中添加一个实例变量(在此问题的范围之外),或者您真的需要它私人的。关联引用不会在编译后的代码中创建任何方法或添加到类的定义中,因此如果您不为它们创建包装器,则在添加数据后不询问对象就不可能找到它们。请参阅我链接的页面底部以获取完整的使用示例。
回答by Anomie
You can use @private
to specify that ivars are private. There is no way to make a method private, however. Even if the method is not listed in the header file, if someone knows the name and arguments they can call it.
您可以使用@private
来指定 ivars 是私有的。但是,无法将方法设为私有。即使头文件中没有列出该方法,如果有人知道名称和参数,他们也可以调用它。