//  GTMFoo.h
         //  FooProject
         //
         //  Created by Greg Miller on 6/13/08.
         //  Copyright 2008 Google, Inc. All rights reserved.
         //

         #import 

         // 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
  1. 使用空格进行缩进,不要在代码中使用制表符,只使用空格,每次缩进两个空格。
  2. 保持每行宽度为80列。
     - (void)doSomethingWithString:(NSString *)theString {
  3. 星号前的空格是可选的。当写新的代码时,要与原的代码一致。 如果一行有非常多的参数,更好的方式是将每个参数单独拆成一行。如果使用多行,将每个参数前的冒号对齐。

  4. 星号前的空格是可选的。当写新的代码时,要与原的代码一致。 如果一行有非常多的参数,更好的方式是将每个参数单独拆成一行。如果使用多行,将每个参数前的冒号对齐。
  5. -或者+与返回类型之间,需要有空格。参数列表中,只有参数之间有空格。  
  6. 方法调用时,所有参数应该在同一行。或者每行一个参数,以冒号对齐。
     [myObject doFooWith:arg1 name:arg2 error:arg3];
            [myObject doFooWith:arg1
                           name:arg2
                          error:arg3];
  7. 方法定义与方法声明一样,当关键字的长度不足以以冒号对齐时,下一行都要以四个空格进行缩进。  

            [myObj short:arg1
                longKeyword:arg2
                evenLongerKeyword:arg3];
  8. @public以及@private访问标识符应该以一个空格缩进。.

  9. 如果你必须使用Objective-C的异常,按下面的格式进行编码代码。然后,请参见避免抛出异常来了解不应该使用异常的原因。
            @try {
              foo();
            }
            @catch (NSException *ex) {
              bar(ex);
            }
            @finally {
              baz();
            }
  10. 每个@标签应该有独立的一行,在@与{}之间需要有一个空格。
  11. 尖括号所包括的协议名称与前面的类型标识之间不应该有空格。
  12. 类名、分类名、协议名用pascal全名法
  13. 局部变量名,方法名,参数名用camel命名法
  14. 字段camel命名法,前加_
  15. 缩写词语全用大写字母
  16. 常量名(如宏、枚举、静态局部变量等)应该以小写字母k开头,使用混合大小写的格式来分隔单词,如:kInvalidHandle,kWritePerm。
  17. 方法名应该读起来就像句子,这表示你应该选择与方法名连在一起读起来通顺的参数名。
  18. 尽量注释很重要,但最好的代码应该自成文档。
  19. 成员变量应该声明为私有。
  20. 当你写子类的时候,如果需要init…方法,记得重写父类的指定的初始化器。
  21. 不要在init方法中,将成员变量初始化为0或者nil,这是冗余的。  
  22. 不要调用NSObject类的类方法new,也不要在子类重写。相反,你应该使用alloc和init方法来创建并初始化一个对象。  
  23. 除非客户端的代码期望使用某个方法,不要把这个方法放进公有的API中。这降低了你不希望被调用的方法被调用的可能性。这包括重写父类的方法。对于内部实现所需要的方法,在实现的文件中定义一个类别,而不是把它们放进公有的头文件中。  
    // GTMFoo.m
            #import "GTMFoo.h"
    
            @interface GTMFoo (PrivateDelegateHandling)
            - (NSString *)doSomethingWithDelegate;  // Declare private method
            @end
    
            @implementation GTMFoo(PrivateDelegateHandling)
            ...
            - (NSString *)doSomethingWithDelegate {
              // Implement this method
            }
            ...
            @end
  24. #import Ojbective-C/Objective-C++头文件,#include C/C++头文件。
  25. 当包含一个使用标准C、C++头文件时,使用#include。头文件应该提供自己的。
  26. 包含根框架而不是单独的文件。 包含顶级根框架编译器要作更少的工作。根框架通常被预编译,并且加载得更快。另外记得使用#import而不是#include来包含Objective-C的框架。
  27. 当创建临时对象时,在同一行使用autolease,而不是在同一个方法的后面语句中使用一个单独的release。
  28. 给对象赋值时遵守autorelease之后retain的模式。
            - (void)setFoo:(GMFoo *)aFoo {
              [foo_ autorelease];  // Won't dealloc if |foo_| == |aFoo|
              foo_ = [aFoo retain];
            }
  29. 接受NSString作为参数的setter,应该copy它所接受的字符串。
            - (void)setFoo:(NSString *)aFoo {
              [foo_ autorelease];
              foo_ = [aFoo copy];
            }
  30. 注意:当使用Objective-C++写基于栈的对象的代码时,如果抛出Objective-C异常,对象不会被清理。
  31. nil检查只用于逻辑流的判断。
  32. Ojbective-C中定义BOOL为无符号字符型,这意味着BOOL类型可以有不同于YES(1)或者NO(0)的值。不要直接把整形转换成BOOL。Objective-C的方法签名中,只使用BOOL。 对BOOL使用逻辑运算符(&&, || 和!)是合法的,返回值也可以安全地转换成BOOL,不需要使用三目操作符。错误的用法:  
            - (BOOL)isBold {
              return [self fontTraits] & NSFontBoldTrait;
            }
            - (BOOL)isValid {
              return [self stringValue];
            }

     正确的用法:  

            - (BOOL)isBold {
              return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
            }
            - (BOOL)isValid {
              return [self stringValue] != nil;
            }
            - (BOOL)isEnabled {
              return [self isValid] && [self isBold];
            }

    同样的,不要直接比较BOOL变量与YES/NO。不仅仅这影响可读性,结果可能与你想的不同。 错误的用法:

            BOOL great = [foo isGreat];
            if (great == YES)
              // ...be great!

    正确的用法

            BOOL great = [foo isGreat];
            if (great)
              // ...be great!

      总结:将常规整形转换成BOOL时要小心,不要直接将BOOL值与YES进行比较。  

  33. 命名 属性所关联的成员变量的命名必须遵守以下划线作为后缀的规则。属性的名字应该与成员变量去掉下划线后缀的名字一模一样。属性的定义必须在@implementation的类定义的最上方。他们的缩进与包含他们的@interface以及@implementation语句一样。
            @interface MyClass : NSObject {
             @private
              NSString *name_;
            }
            @property(copy, nonatomic) NSString *name;
            @end
    
            @implementation MyClass
            @synthesize name = name_;
            - (id)init {
            ...
            }
            @end
  34. NSString属性应该永远被声明为copy特性。 这从逻辑上遵守了NSString的setter必须使用copy而不是retain。
  35.  不要synthesize CFType的属性 CFType应该永远使用@dynamic实现指示符。 在错误的做法:  
            @interface MyClass : NSObject
            @property(readonly) NSString *name;
            @end
    
            @implementation MyClass
            .
            .
            .
            - (NSString*)name {
              return @"foo";
            }
            @end

    正确的做法

            @interface MyClass : NSObject
            @property(readonly) NSString *name;
            @end
    
            @implementation MyClass
            @dynamic name;
            .
            .
            .
            - (NSString*)name {
              return @"foo";
            }
            @end
  36. 原子性 一定要注意属性的开销。所有synthesize的setter和getter都是原子的。这会给每个get或者set带来一定的同步开销。显示将你的属性声明为nonatomic除非你需要原子操作。
  37.  实现委托模式的类应该,
    • 拥有一个名为delegate_的成员变量来引用委托。
    • 因此,访问器方法应该名为delegate和setDelegate:。
    • delegate_对象不应该被retained。
  38. 分离模型与视图。分离控制器与视图、模型。回调API使用@protocol。
    • 模型与视图分离:不要假设模型或者数据源的表示方法。保持数据源与表示层之间的接口抽象。视图不需要了解模型的逻辑(主要的规则是问问你自己,对于数据源的一个实例,有没有可能有多种不同状态的表示方法)。
    • 控制器与模型、视图分离:不要把所有的“领域逻辑”放进跟视图有关的类中。这命名得代码非常难以重用。使用控制器来写这些代码,但保证控制器不需要了解太多表示层的逻辑。
    • 使用@protocol来定义回调API,如果不是所有的方法都必须实现,使用@optional(例外:当使用Objective-C 1.0,@optional不可用,因此请使用类别来定义“非正式的协议”)。