How to make a real private instance variable?
Solution 1
You can use the @private
keyword inside the {}
to make all subsequent variable declarations private. The default visibility is @protected
(which is similar to protected
in Java) and that generally works well. You'd have to specifically declare a variable as @public
for it to be directly accessible outside the class.
This Apple documentation has further details about variable scope and visibility.
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:
- About private instance variables in Objective-C
- What does “@private” mean in Objective-C?
- Is it possible to declare a method as private in Objective-C?
- Best way to define private methods for a class in Objective-C
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.
Solution 2
With the new LLVM Compiler available in XCode 4 and later, you can declare @private
variables in default categories inside your implementation (.m) file:
@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.
Solution 3
You can define private methods by simply having them only in the @implementation, and not the @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.
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.
If you were making a library, though, theoretically no one would know about any methods you didn't declare in the header files.
Solution 4
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.
The two exceptions are categories and subclasses.
Solution 5
I saw the following usage in a sample app (PaintGL) by Apple
In .m file
@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
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on January 04, 2020Comments
-
Admin over 4 years
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.
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.
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.
What's the trick here?
-
Jason Coco almost 15 yearsThey will be able to interact with them through valueForKey: and setValue:forKey: however.
-
rpetrich almost 15 yearsObjective-C now allows for adding IVars to a class without affecting the subclasses (with the 2.0 language update that came with Leopard and iPhone OS 2.0)
-
user102008 almost 13 years"sort of like in Java" No, in Java, the default access is very different from "protected"
-
jpswain almost 13 yearsThis DOES NOT work with LLVM GCC 4.2 and Xcode 4.0.2 targeting iOS 4.2. Did you mean "LLVM 2.0 compiler"?
-
aaddesso almost 13 yearsLLVM GCC is NOT the LLVM compiler, it's still GCC but with the LLVM parser. I meant LLVM 2.0 or LLVM 3.0 (iOS 5 Beta, XCode 4.2).
-
jpswain almost 13 yearsAh sorry about that. It may be important though to be aware of this only working with this one compiler especially for people working on a project with others.
-
chakrit almost 13 yearsHe means that ObjC's "protected" is just like java's "protected".
-
Quinn Taylor almost 13 yearsSorry for the confusion, I clarified my answer slightly. You're correct that Java's 'default' access is very different from 'protected'. I didn't mean to conflate the two.
-
Raffi Khatchadourian over 12 years@QuinnTaylor Right, the default package protected visibility shouldn't apply in Objective-C since there are no packages.
-
Raffi Khatchadourian over 12 yearsYou can use a
@protocol
to "hide" your instance variables from clients. -
aaddesso about 12 years@JohanPelgrim: Ah yes, coding too much C++ I reckon
-
eonil almost 12 years@RaffiKhatchadourian It's not the purpose of
@protocol
. And does not help hiding ivar from class. It just hide the whole class. And you should make your own answer entry if you want to offer an answer. -
Raffi Khatchadourian almost 12 years@Eonil Yes, I agree that hiding instance variable from clients is not the purpose of
@protocol
, but it would seem to answer the comment given about "polluting" header files with private variables. -
ArtOfWarfare about 11 years"theoretically no one would know about any methods you didn't declare in the header files." - Not so. I've been able to write a pretty invasive Xcode plugin despite Apple's lack of documentation about their hundreds of private methods by utilizing functions from the objc_runtime.h which tell you exactly what the methods are that a class has.