What Does "@Private" Mean in Objective-C

What does @private mean in Objective-C?

It's a visibility modifier—it means that instance variables declared as @private can only be accessed by instances of the same class. Private members cannot be accessed by subclasses or other classes.

For example:

@interface MyClass : NSObject
{
@private
int someVar; // Can only be accessed by instances of MyClass

@public
int aPublicVar; // Can be accessed by any object
}
@end

Also, to clarify, methods are always public in Objective-C. There are ways of "hiding" method declarations, though—see this question for more information.

What does the @package directive do in Objective-C?

@package is similar to internal for .NET. It means the member is accessible only from the framework in which it is defined.

Note: In 32-bit it acts like @public.

Is this a new way to define private instance variables in Objective-C?

It's for real, it's the new way,* it's great, and, yes, it's in the docs. The Objective-C Programming Language, which is as close as we get to having an actual spec for the language, has the following to say:

The definition of a class is structured very much like its declaration. It begins with an @implementation directive and ends with the @end directive. In addition, the class may declare instance variables in braces after the @implementation directive:

@implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
@end

There's also a historical note a little ways back from that link, addressing the fact that we used to have to declare ivars in the interface block:

Historically, the interface required declarations of a class’s instance variables, the data structures that are part of each instance of the class. ... Instance variables represent an implementation detail, and should typically not be accessed outside of the class itself. Moreover, you can declare them in the implementation block or synthesize them using declared properties. Typically you should not, therefore, declare instance variables in the public interface and so you should omit the braces.

For the question of privacy, yes, these variables are truly private -- they act like ivars declared in the interface with the @private directive. This means that subclasses can't access them, by default. Their visibility can be changed, however, using either @protected or (if necessary for some bizarre reason) @public:

@interface Stuper : NSObject 
@end

@implementation Stuper
{
@protected
NSString * sangfroid;
}
@end

@interface Stub : Stuper
- (void)setSangfroid: (NSString *)newSangfroid;
@end

@implementation Stub

- (void)setSangfroid: (NSString *)newSangfroid {
sangfroid = [newSangfroid copy];
}

*You have to use clang > 3.0, I believe, so that's just a few months ago as of this posting. GCC won't do it.

Private and protected methods in Objective-C

There are three issues:

  1. Hiding from compiler.

    That is, making it impossible for someone else to #import something and see your method declarations. For that, put your private API into a separate header file, mark that header's role as "Private" in Xcode, and then import it in your project where you need access to said private API.

    Use a category or class extension to declare the additional methods.

  2. Preventing collisions

    If you are implementing lots of internal goop, do so with a common prefix or something that makes a collision with Apple provided (or third party) provided methods exceedingly unlikely. This is especially critical for categories and not nearly as critical for your leaf node subclasses of existing classes.

    Post the link for the site suggesting leading underscores, as they are wrong, wrong, wrong. Leading underscores are used by the system to mark private API and you can run into collisions easily enough.

  3. Hiding from the runtime.

    Don't bother. It just makes debugging / crash analysis harder and anyone determined enough to muck around at the runtime will be able to hack your app anyway.

How do I use this private API?

Have you tried calling performSelector? That is usually the trick to call private methods. Remember all that makes a method private in Objective-C is the fact that it is not advertised in the h file. But if you send a message to an object and the object can respond to that message it will, regardless of what's in the header file.

Accessing hidden private class in Objective-C

The attribute keyword is simply a message to the compiler, and has nothing to do with the runtime. Using ((visibility("xxx")) only serves to tell the compiler if the given declaration should be "visible" or usable by clients in some other package. visibility("hidden") just means that, despite the public declaration, make this thing invisible to external packages, so that they will not be able to use it. Compiling will fail if you attempt to use this class or method.

If you don't see this class being used in a recursive description, it is likely that this class is no longer used; it certainly isn't because of the attribute statement.



Related Topics



Leave a reply



Submit