views:

208

answers:

2

If I have a class with some IBOutlets, it seems kind of silly to create accessors for these.

But then I feel like I'm breaking OO practices by not always going through the accessors for instance variables.

I also feel the same way about some instance variables that should not be public, I'd rather not expose the inner workings of some classes. I can make the actual ivars private but the @property shorthand doesn't seem to be able to specify visibility. This leads me to not create accessors and just access the ivars directly. I'm not sure if this is frowned upon though. Is it?

What's the community's thoughts on this admittedly newbie question? (Please ignore dot syntax)

+3  A: 

I'm not sure about accessing instance variables directly, I think one shouldn't, but for some variables it just doesn't make sense to use accessors. Like for the IBOutlets you mentioned.

I can only help you out with private accessors. Starting with Objective-C 2.0 you can declare extensions.

Class extensions are like “anonymous” categories, except that the methods they declare must be implemented in the main @implementation block for the corresponding class.

Just put this extension into a separate header file and you'll have private accessors that aren't visible in the header.

Georg
+1  A: 

Public/Private

You can declare your iVars as in the @interface file to be readonly, but then re-declare them in a category so that your class can change them. Here's a quick intro to Categories.

An example:

//MyClass.h

@interface MyClass : NSObject {
    NSString *name;
}
@property (readonly) NSString *name;

@end

And in the implementation file you can redeclare this:

//MyClass.m
@interface MyClass () //declare the class extension

@property (readwrite, copy) NSString *name; //redeclare the property

@end

@implementation MyClass

@synthesize name;

@end

Now, the name property is readonly external to the class, but can be changed by the class through property syntax or setter/getter syntax.

Really private iVars

If you want to keep iVars really private and only access them directly without going through @property syntax you can declare them with the @private keyword. But then you say "Ah, but they can always get the value outside the class using KVC methods such as setValueForKey:" In which case take a look at the NSKeyValueCoding protocol class method + (BOOL)accessInstanceVariablesDirectly which stops this.

IBOutlets as properties

The recommended way is to use @property and @synthesize. For Mac OS X, you can just declare them as readonly properties. For example:

//MyClass.h

@interface MyClass : NSObject {
    NSView *myView;
}
@property (readonly) IBOutlet NSView *myView;

@end

//MyClass.m

@implementation MyClass

@synthesize myView;

@end
Abizern