-
Notifications
You must be signed in to change notification settings - Fork 573
Code style guide
Always keep in mind that this is a framework. Even seemingly small changes can have widespread (and sometimes catastrophic) ramifications in applications that use the framework. Programming within the framework may require a different mindset than programming for the framework.
To keep the project maintainable and easy to approach by newcomers, we need to agree upon at least some rudimentary styles. These aren't necessarily the greatest standards ever, but as long as they are consistent it should make things easier for everyone in the long run.
While I prefer tabs, I think Xcode may be defaulting to 4 spaces now. So use either real tabs or 4 spaces to indent stuff.
Put the curly braces of method bodies on their own lines, but inline for if/else/etc blocks:
- (void)addClip
{
[self _setContextPath];
if (_usesEvenOddFillRule) {
CGContextEOClip(UIGraphicsGetCurrentContext());
} else {
CGContextClip(UIGraphicsGetCurrentContext());
}
}
When declaring a property, I prefer this format/spacing around the various elements of the declaration:
@property (nonatomic, readonly, getter=isVisible) BOOL visible;
When synthesizing, I tend to prefer putting them all in a huge block at the top which only gets about as wide as my screen happens to be at the time. I know some people like to give each one their own line which has a logic to it, but can get very tall in some cases. Either way works. :)
@implementation UIActionSheet
@synthesize delegate=_delegate, destructiveButtonIndex=_destructiveButtonIndex, cancelButtonIndex=_cancelButtonIndex, title=_title;
@synthesize firstOtherButtonIndex=_firstOtherButtonIndex, actionSheetStyle = _actionSheetStyle;
In -init
methods, I prefer this as a generic structure. I don't know why, exactly, but it feels most compact to me while also visually calling out the -init
methods as being "different" and worthy of special consideration.
- (id)initWithFrame:(CGRect)frame
{
if ((self=[super initWithFrame:frame])) {
_menuTitles = [[NSMutableArray alloc] init];
_separatorIndexes = [[NSMutableArray alloc] init];
_destructiveButtonIndex = -1;
_cancelButtonIndex = -1;
_firstOtherButtonIndex = -1;
}
return self;
}
I strongly prefer that member variables in initializers have default values assigned to them directly rather than using property accessors. My reasoning is that in init
the object is not necessarily fully "ready" yet and calling a setter could have unintended side-effects because we cannot know if application code has perhaps subclassed and overridden the setter to do something unexpected. That said, it is not always possible to avoid a setter in an init
method - just be aware of the potential for trouble.
In -dealloc
it is my position that it is never ever the right thing to call a setter. Release member variables directly. Do not do something like self.property = nil;
. As rule, you should do as little as possible in -dealloc
and calling a setter does not qualify as "little" in my mind. Also remember that under garbage collection, -dealloc
is never called. Only use -dealloc
to release objects (and remove observers). Setting a member variable to nil after releasing isn't a bad thing, though, even in dealloc
as that can aid in debugging. I tend not to do that myself, but it's not a bad idea. :)
For member variables and internal methods, prefix them with an underscore to reduce the chance of conflicting with applications which may subclass framework classes.
If you need to reference private methods from outside of a class implementation, create a UIPrivate
category in its own file to keep it out of the public header file. See the other files with private headers to learn the conventions being used in this case.
If you need a non-standard extension to a class, put that interface in an AppKitIntegration
category. Again, put this category in its own file and do not include it in any public headers except for AppKitIntegration.h
. Keep the default public interface to Chameleon as identical to Apple's interfaces as possible. AppKitIntegration extensions are opt-in by third party apps.
Whenever possible, don't allow AppKit's names to "infect" the Chameleon namespace. Don't include AppKit headers from Chameleon headers. Forward declarations are okay, but I still like to try to avoid them - although not at the expense of making things painful.
Always import the minimum/most-specific header files necessary to get the job done. Don't do a blanket include of UIKit.h
, for example.
Try to avoid forward-delcaring methods. If you have to reference a private method in one class from another class, make or import a UIPrivate
category header instead. I consider forward declaration of methods to fall under the "don't repeat yourself" agile rule.
Read and apply the Cocoa Coding Guidelines http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html.