views:

930

answers:

3

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?

+6  A: 

You can use the @private keyword inside the {} to make all subsequent variable declarations private. The default visibility is @protected, sort of like 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:

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.

Quinn Taylor
+3  A: 

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.

kubi
They will be able to interact with them through valueForKey: and setValue:forKey: however.
Jason Coco
I had no idea that KVC worked like that, thanks for posting. Turns out you can turn this behavior off by overriding `+ (BOOL)accessInstanceVariablesDirectly` to return NO.
kubi
+1  A: 

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.

http://bit.ly/8Ittm (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.

criscokid
Objective-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)
rpetrich