原文
iPhone项目新成立,也没有编码规范的积累,项目组本来是想拿老的C编码规范套用的,但评审一下就发现问题多多,之后找到了Google的Objective-C的编码规范,大家就先翻译一下咯 声明这是无版权翻译,也不对任何错误负责,不保证文章的完整性,我到现在也认不全语法。(大半年的事后,决定对这份文档做重审,当然不是对修辞手法,而是处理内部的硬伤)
总览 背景知识 Objective-C是一个C语言的扩展语言,非常动态,非常的“面向对象”,它被设计成既拥有复杂的面向对象设计理念又可以轻松使用与阅读的语言,也是Mac OS X和iPhone开发的首选语言。 Cocoa是Mac OS X的主要应用框架,提供迅速开发各种功能的Mac OS X应用的Objective-C类集合。 Apple已经有一个很好也被广泛接受的Objective-C的编码规范,Google也有类似的C++编码规范,这份Objective-C编码规范很自然是Apple和Google的共同推荐的组合。所以,在阅读本规范前,确保你已经阅读了: 注意所有已在Google的C++编码规范里的禁用条款在Objective-C里也适用,除非本文档明确指出反对意见。 本文档旨在描述可供可适用于所有Mac OS X代码的Objective-C(包括Objective-C++)编码规范和实践。规范中的许多条款已经改进也不断的被其他的项目和团队所证明其指导性。Google的相关开源项目都遵守此规范。 Google已经发布了一份作为 (文档中简称为GTM)的组成部分的遵守本规范的开源代码。这份开放代码也是本文很好的例证(原文看不太懂--Code meant to be shared across different projects is a good candidate to be included in this repository. ) 注意本文不是Objective-C的教学指南,我们假设读者已经了解语言。如果你是一个Objective-C的初学者或需要重温,请阅读 .示例 人们说一个例子胜过千言万语,所以就让我们用例子来让你感受以下编码规范的风格,留间距,命名等等。 下例是一份头文件,展示对@interface 声明正确的注释和留间距- // GTMFoo.h
- // FooProject
- //
- // Created by Greg Miller on 6/13/08.
- // Copyright 2008 Google, Inc. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- // A sample class demonstrating good Objective-C style. All interfaces,
- // categories, and protocols (read: all top-level declarations in a header)
- // MUST be commented. Comments must also be adjacent to the object they're
- // documenting.
- //
- // (no blank line between this comment and the interface)
- @interface GTMFoo : NSObject {
- @private
- NSString *foo_;
- NSString *bar_;
- }
- // Returns an autoreleased instance of GMFoo. See -initWithString: for details
- // about the argument.
- + (id)fooWithString:(NSString *)string;
- // Designated initializer. |string| will be copied and assigned to |foo_|.
- - (id)initWithString:(NSString *)string;
- // Gets and sets the string for |foo_|.
- - (NSString *)foo;
- - (void)setFoo:(NSString *)newFoo;
- // Does some work on |blah| and returns YES if the work was completed
- // successfuly, and NO otherwise.
- - (BOOL)doWorkWithString:(NSString *)blah;
- @end
- //
- // GTMFoo.m
- // FooProject
- //
- // Created by Greg Miller on 6/13/08.
- // Copyright 2008 Google, Inc. All rights reserved.
- //
- #import "GTMFoo.h"
- @implementation GTMFoo
- + (id)fooWithString:(NSString *)string {
- return [[[self alloc] initWithString:string] autorelease];
- }
- // Must always override super's designated initializer.
- - (id)init {
- return [self initWithString:nil];
- }
- - (id)initWithString:(NSString *)string {
- if ((self = [super init])) {
- foo_ = [string copy];
- bar_ = [[NSString alloc] initWithFormat:@"hi %d", 3];
- }
- return self;
- }
- - (void)dealloc {
- [foo_ release];
- [bar_ release];
- [super dealloc];
- }
- - (NSString *)foo {
- return foo_;
- }
- - (void)setFoo:(NSString *)newFoo {
- [foo_ autorelease];
- foo_ = [newFoo copy];
- }
- - (BOOL)doWorkWithString:(NSString *)blah {
- // ...
- return NO;
- }
- @end
- - (void)doSomethingWithString:(NSString *)theString {
- ...
- }
- - (void)doSomethingWith:(GTMFoo *)theFoo
- rect:(NSRect)theRect
- interval:(float)theInterval {
- ...
- }
- - (void)short:(GTMFoo *)theFoo
- longKeyword:(NSRect)theRect
- evenLongerKeyword:(float)theInterval {
- ...
- }
- [myObject doFooWith:arg1 name:arg2 error:arg3];
- [myObject doFooWith:arg1
- name:arg2
- error:arg3];
- [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg
- error:arg3];
- [myObject doFooWith:arg1
- name:arg2 error:arg3];
- [myObject doFooWith:arg1
- name:arg2 // aligning keywords instead of colons
- error:arg3];
- [myObj short:arg1
- longKeyword:arg2
- evenLongerKeyword:arg3];
- @interface MyClass : NSObject {
- @public
- ...
- @private
- ...
- }
- @end
- @try {
- foo();
- }
- @catch (NSException *ex) {
- bar(ex);
- }
- @finally {
- baz();
- }
.h | C/C++/Objective-C header file |
.m | Objective-C implementation file |
.mm | Objective-C++ implementation file |
.cc | Pure C++ implementation file |
.c | C implementation file |
- // file: cross_platform_header.h
- class CrossPlatformAPI {
- public:
- ...
- int DoSomethingPlatformSpecific(); // impl on each platform
- private:
- int an_instance_var_;
- };
- // file: mac_implementation.mm
- #include "cross_platform_header.h"
- // A typical Objective-C class, using Objective-C naming.
- @interface MyDelegate : NSObject {
- @private
- int instanceVar_;
- CrossPlatformAPI* backEndObject_;
- }
- - (void)respondToSomething:(id)something;
- @end
- @implementation MyDelegate
- - (void)respondToSomething:(id)something {
- // bridge from Cocoa through our C++ backend
- instanceVar_ = backEndObject->DoSomethingPlatformSpecific();
- NSString* tempString = [NSString stringWithInt:instanceVar_];
- NSLog(@"%@", tempString);
- }
- @end
- // The platform-specific implementation of the C++ class, using
- // C++ naming.
- int CrossPlatformAPI::DoSomethingPlatformSpecific() {
- NSString* temp_string = [NSString stringWithInt:an_instance_var_];
- NSLog(@"%@", temp_string);
- return [temp_string intValue];
- }
- - (id)getDelegate; // AVOID
- - (id)delegate; // GOOD
- // AVOID
- int w;
- int nerr;
- int nCompConns;
- tix = [[NSMutableArray alloc] init];
- obj = [someObject object];
- p = [network port];
- // GOOD
- int numErrors;
- int numCompletedConnections;
- tickets = [[NSMutableArray alloc] init];
- userInfo = [someObject object];
- port = [network port];
- // A delegate for NSApplication to handle notifications about app
- // launch and shutdown. Owned by the main app controller.
- @interface MyAppDelegate : NSObject {
- ...
- }
- @end
- // Sometimes we need |count| to be less than zero.
- // Remember to call |StringWithoutSpaces("foo bar baz")|
- @interface MyDelegate : NSObject {
- @private
- IBOutlet NSButton* okButton_; // normal NSControl
- IBOutlet NSMenu* myContextMenu_; // manually-loaded menu (strong)
- AnObjcObject* doohickey_; // my doohickey
- MyController* controller_; // so we can send msgs back (weak, owns me)
- // non-NSObject pointers...
- CWackyCPPClass* wacky_; // some cross-platform object (strong)
- CFDictionaryRef* dict_; // (strong)
- }
- @end
- @interface MyClass : NSObject {
- @private
- id myInstanceVariable_;
- }
- // public accessors, setter takes ownership
- - (id)myInstanceVariable;
- - (void)setMyInstanceVariable:(id)theVar;
- @end
- // GTMFoo.m
- #import "GTMFoo.h"
- @interface GTMFoo (PrivateDelegateHandling)
- - (NSString *)doSomethingWithDelegate; // Declare private method
- @end
- @implementation GTMFoo(PrivateDelegateHandling)
- ...
- - (NSString *)doSomethingWithDelegate {
- // Implement this method
- }
- ...
- @end
- @interface GMFoo () { ... }
- #import <Cocoa/Cocoa.h>
- #include <CoreFoundation/CoreFoundation.h>
- #import "GTMFoo.h"
- #include "base/basictypes.h"
- #import <Foundation/Foundation.h> // good
- #import <Foundation/NSArray.h> // avoid
- #import <Foundation/NSString.h>
- ...
- // AVOID (unless you have a compelling performance reason)
- MyController* controller = [[MyController alloc] init];
- // ... code here that might return ...
- [controller release];
- // BETTER
- MyController* controller = [[[MyController alloc] init] autorelease];
- - (void)setFoo:(GMFoo *)aFoo {
- [foo_ autorelease]; // Won't dealloc if |foo_| == |aFoo|
- foo_ = [aFoo retain];
- }
- - (void)setFoo:(NSString *)aFoo {
- [foo_ autorelease];
- foo_ = [aFoo copy];
- }
- class exceptiontest {
- public:
- exceptiontest() { NSLog(@"Created"); }
- ~exceptiontest() { NSLog(@"Destroyed"); }
- };
- void foo() {
- exceptiontest a;
- NSException *exception = [NSException exceptionWithName:@"foo"
- reason:@"bar"
- userInfo:nil];
- @throw exception;
- }
- int main(int argc, char *argv[]) {
- GMAutoreleasePool pool;
- @try {
- foo();
- }
- @catch(NSException *ex) {
- NSLog(@"exception raised");
- }
- return 0;
- }
- 2006-09-28 12:34:29.244 exceptiontest[23661] Created
- 2006-09-28 12:34:29.244 exceptiontest[23661] exception raised
- // AVOID
- - (BOOL)isBold {
- return [self fontTraits] & NSFontBoldTrait;
- }
- - (BOOL)isValid {
- return [self stringValue];
- }
- // GOOD
- - (BOOL)isBold {
- return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
- }
- - (BOOL)isValid {
- return [self stringValue] != nil;
- }
- - (BOOL)isEnabled {
- return [self isValid] && [self isBold];
- }
- // AVOID
- BOOL great = [foo isGreat];
- if (great == YES)
- // ...be great!
- // GOOD
- BOOL great = [foo isGreat];
- if (great)
- // ...be great!
- @interface MyClass : NSObject {
- @private
- NSString *name_;
- }
- @property(copy, nonatomic) NSString *name;
- @end
- @implementation MyClass
- @synthesize name = name_;
- @end
- @interface MyClass : NSObject {
- @private
- NSString *name_;
- }
- @property(copy, nonatomic) NSString *name;
- @end
- @implementation MyClass
- @synthesize name = name_;
- - (id)init {
- ...
- }
- @end
- // AVOID
- @interface MyClass : NSObject
- @property(readonly) NSString *name;
- @end
- @implementation MyClass
- .
- .
- .
- - (NSString*)name {
- return @"foo";
- }
- @end
- // GOOD
- @interface MyClass : NSObject
- @property(readonly) NSString *name;
- @end
- @implementation MyClass
- @dynamic name;
- .
- .
- .
- - (NSString*)name {
- return @"foo";
- }
- @end
- NSString *upperCase = @"foo".uppercaseString;
- bar.value += 10;