views:

186

answers:

4

Why are people using

@interface ViewController : UIViewController 
{
@private
    UIButton* button_;
}

@private declarations in public headers? Declaring a variable inside an implementation yields the same result, doesn't it? It feels strange to me, I thought a public header should only contain really public members. What to do with protected members?

@implementation ViewController
    UIButton* button_;
@end

The only difference I know of is that this variable is only visible inside the current compilation unit (the .m file, right?)

Does the same hold true for methods? I could compile fine with proper method ordering or forward declarations. Why do people care to declare categories for private methods? For testing purposes only?

A: 

@private is referring only to the iVars.

By default you can access ivars of an instance like so:- id iShouldNotDoThis = foo->bar;

@private means you can't access the ivar like that and have to use the access methods.

id thisIsBetter = [foo bar];

Nothing to do with private categories or methods.

wouldn't i get a compiler/linker error when trying to access button_ if it was only declared inside the implementation file?
Johannes Rudolph
it's not in the implementation file.. it's in the public header, declared @private
sorry, i meant MY example aboce where button_ is declared int the implementation file
Johannes Rudolph
ahh, i see. The first option you have is like i describe above. The second option is completely different, as pgb says - a C global variable (That doesn't mean that it is static)
+5  A: 

The variable declaration inside the @implementation block will create a global variable, and not an instance variable. Instance variables need to be defined as part of the @interface.

While you can create an additional @interface block, by means of a category or extension, but it can only contain method declarations, and not instance variables.

pgb
that's not what i would expect!!! Does that mean they are static also?
Johannes Rudolph
I think they are not, it's just a global variable in the `C` way of declaring things. Remember that `Objective-C` is a strict superset of `C`, so all `C` rules still apply.
pgb
i have confirmed it is a global variable, you we're right. I'm surprised the compiler does not issue a warning when declaring a non-static variable _inside_ @implementation
Johannes Rudolph
warning you of what? Declaring a standard global variable?
You can't declare them in an separate interface block. Only the original class @interface block can declare instance variables. I think you can create a class extension or category to declare additional methods only.
Barry Wark
You are right. I'll correct the post.
pgb
+3  A: 

I would say that while it might "feel" wrong to you to put private instance variables in a supposedly public header, I wouldn't worry about it.

Take a look at pretty much any header file for a Cocoa class (except for the cluster classes), and you'll see that Apple declares their instance variables in their public header files.

Since Apple is OK with it, I don't think you have much to worry about. =)

FYI: All instance variables are protected by default.

Dave DeLong
+3  A: 

Does the same hold true for methods?

No, methods are visible to any part of the program. If you know the selector you can callit.

I could compile fine with proper method ordering or forward declarations. Why do people care to declare categories for private methods? For testing purposes only?

Private categories are a form of forward declaration. You can think of them as if they were C prototypes.

Andrew

adonoho