Skip to content

Latest commit

 

History

History
490 lines (340 loc) · 18.7 KB

README_ja-JP.md

File metadata and controls

490 lines (340 loc) · 18.7 KB

NYTimes Objective-C スタイルガイド

このスタイルガイドは、ニューヨーク・タイムズでの iOS チームのコーディング規約です。issuespull requestsつぶやきへのフィードバックを歓迎します。また、人材募集中です。

貢献者の皆さんに感謝します。

はじめに

Appleからいくつかのスタイルガイド情報が提供されています。ここで述べられていないことは、それらを参考にしてください:

目次

ドット表記構文

プロパティのアクセスや変更する際に必ずドット表記を使うこと。それ以外の場合は大括弧表記を使うこと。

良い例:

view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate;

悪い例:

[view setBackgroundColor:[UIColor orangeColor]];
UIApplication.sharedApplication.delegate;

スペーシング

  • スペース4つでインデントすること。タブキーでインデントしない。Xcodeで設定するように。
  • メソッドの中括弧とその他の中括弧(if/else/switch/whileなど)は始め中括弧を同じ行で書き、終わり中括弧を改行で書くこと。

良い例:

if (user.isHappy) {
    // 何かをする
}
else {
    // 他の何かをする
}
  • 見た目を分かりやすくするために、メソッド間は一行開けること。
  • メソッド内の機能を分けるために一行開けること(ただ、これはメソッドをより小さく分割すべきという兆候でもある)。長く詳細な名前のメソッドでは、見た目を分けるためにメソッド名と中身の間を一行開けること。
  • @synthesize@dynamicは一行ずつ宣言すること。

条件文

条件文は常に中括弧を使うこと。たとえそれが中括弧なしで書ける場合(例えば、一行文)であってもである。それによって、間違いを防ぐことができる。ありがちな間違いとして、行を追記する際に直前のif文に追加されたものとする勘違いがある。他にも、if文内の1行がコメントアウトされると、次の1行がうっかりif文の一部となってしまうというより危険な問題もある。このスタイルの良い点として、他の全ての条件文と見た目が一貫するため、読み取りやすくなる。

良い例:

if (!error) {
    return success;
}

悪い例:

if (!error)
    return success;

または

if (!error) return success;

三項演算子

三項演算子 ? は分かりやすくなる場合のみ使うこと。

良い例:

result = a > b ? x : y;

悪い例:

result = a > b ? x = c > d ? c : d : y;

エラー処理

メソッドがエラーの返戻値の参照を返す場合、条件はエラー変数を使わずに、返戻値を使うこと。

良い例:

NSError *error;
if (![self trySomethingWithError:&error]) {
    // エラー処理
}

悪い例:

NSError *error;
[self trySomethingWithError:&error];
if (error) {
    // エラー処理
}

AppleのAPIのいくつかは、成功時にエラー変数へゴミ値を入れる。そのためエラー変数を条件に使う場合、エラー発生したと誤判定される(そしてクラッシュする)。

メソッド

メソッドシグネチャでは、メソッドのスコープ(-+シンボル)の後にスペースを開けること。メソッドのセグメント間にスペースを開けること。

良い例:

- (void)setExampleText:(NSString *)text image:(UIImage *)image;

変数

変数名をわかりやすく命名すること。その変数が表すものやプログラマーに必要な関連情報を提供することにより、値を適切に使えるようになります。

良い例:

  • NSString *title: “title”を文字列とするのは妥当です。
  • NSString *titleHTML: 表示用にパースする必要のあるHTMLを含んだタイトルのこと。プログラマーがこの変数を効果的に利用するために“HTML”が付加されています。
  • NSAttributedString *titleAttributedString: 表示用に整形済みのタイトル。 AttributedStringから、この値がただのありきたりなタイトルではないことがわかります。これを加えることは文脈に則していて妥当であるといえます。
  • NSDate *now: これ以上の分かりやすさはないでしょう。
  • NSDate *lastModifiedDate: 単純にlastModified だけだと曖昧です。しかし文脈に応じて明確になります。
  • NSURL *URLNSString *URLString: ある値が異なるクラスにより表現される場合、それを変数名にすることで分かりやすくなります。
  • NSString *releaseDateString: ある値が別のクラスにより表現される別例です。この名前により分かりやすくなっています。

ループ中の単純なカウンター変数以外では、一文字の変数名は使わないこと。

ポインタ型で使うアスタリスクは、変数名側に付けること。良い例は、NSString *textです。悪い例は、NSString* textNSString * textです。ただし定数は除く(NSString * const NYTConstantString)。

できれば素のインスタンス変数を使わずにプロパティで宣言すること。インスタンス変数への直接アクセスは避けること。ただし初期化メソッド(initinitWithCoder:、その他…)、deallocメソッド、setterとgetterを除く。詳細は初期化メソッドとdealloc内のアクセサメソッド利用に関するAppleの文書を参照すること。

良い例:

@interface NYTSection: NSObject

@property (nonatomic) NSString *headline;

@end

悪い例:

@interface NYTSection : NSObject {
    NSString *headline;
}

変数修飾子

ARCにより導入された変数修飾子は、(__strong__weak__unsafe_unretained__autoreleasing)アスタリスクと変数名の間におくこと。例えばNSString * __weak text

命名

できればAppleの命名規約に従うこと。特にこれはメモリ管理ルール (NARC)に関連があります。

メソッド名や変数名は、長くてわかりやすいのが良い。

良い例:

UIButton *settingsButton;

良い例:

UIButton *setBut;

三文字接頭辞(例えばNYT)をクラス名や定数名にいつも使うこと。ただし、Core Dataエンティティ名は除く。定数名はキャメルケースで全ての先頭文字を大文字にし、関連クラス名を接頭辞にすること。二文字接頭辞(例えばNS)はAppleに予約されています

良い例:

static const NSTimeInterval NYTArticleViewControllerNavigationFadeAnimationDuration = 0.3;

悪い例:

static const NSTimeInterval fadetime = 1.7;

プロパティ名とローカル変数名は、キャメルケースで最初の文字を小文字にすること。

インスタンス変数はキャメルケースで最初の文字を小文字にし、アンダースコアを接頭辞にすること。これにより、LLVMが自動的にsynthesizeしたインスタンス変数と一貫性を保つことができます。LLVMの自動synthesizeはそのままにしておくこと。

良い例:

@synthesize descriptiveVariableName = _descriptiveVariableName;

悪い例:

id varnm;

カテゴリ

カテゴリは機能を簡潔に表現する名前にすること。

良い例:

@interface UIViewController (NYTMediaPlaying)
@interface NSString (NSStringEncodingDetection)

悪い例:

@interface NYTAdvertisement (private)
@interface NSString (NYTAdditions)

コメント

コメントは必要の場合のみ書く。処理の理由を説明すること。コメントの更新することを忘れずに。必要がなくなったら削除すること。

ブロックコメントをなるべく書かないこと。できるだけコード自身に自己説明させること。ドキュメント生成用のコメントは例外。

初期化と解放

deallocメソッドは実装部の最初、@synthesize@dynamic宣言の直後に書くこと。initdeallocメソッドの直後に書くこと。

initメソッドを次のように書くこと。

- (instancetype)init {
    self = [super init]; // または指定の初期化メソッド
    if (self) {
        // カスタマイズ初期化処理
    }

    return self;
}

リテラル

NSStringNSDictionaryNSArrayNSNumberリテラルを使うこと。これらのオブジェクトの不変インスタンスを作る場合は常にです。nilNSArrayNSDictionary リテラルに入れないこと。クラッシュします。

良い例:

NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingZIPCode = @10018;

悪い例:

NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];
NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];
NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];
NSNumber *buildingZIPCode = [NSNumber numberWithInteger:10018];

CGRect 関数

CGRectx,y,width,heightにアクセスする際、構造体メンバーに直接アクセスせずに必ず CGGeometry関数を使うこと。AppleのCGGeometry レファレンスより:

このレファレンス中の関数でCGRectデータ構造を入力とするものは、矩形を暗黙的に標準化してから結果を計算する。そのため、アプリケーションはCGRectデータ構造内のデータを直接読み書きすべきではない。かわりに、ここに記載されている関数を使って矩形計算し、値を取得すること。

良い例:

CGRect frame = self.view.frame;

CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);

悪い例:

CGRect frame = self.view.frame;

CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;

定数

インライン文字列や数値をなるべく定数で宣言するように。その方があとで変更しやすい。定数を#defineではなくstaticで宣言するように。ただし明らかにマクロで使われる場合は除く。

良い例:

static NSString * const NYTAboutViewControllerCompanyName = @"The New York Times Company";

static const CGFloat NYTImageThumbnailHeight = 50.0;

悪い例:

#define CompanyName @"The New York Times Company"

#define thumbnailHeight 2

列挙型

列挙型定数を宣言する際、enumではなく新しい列挙型NS_ENUM()を使うように。

良い例:

typedef NS_ENUM(NSInteger, NYTAdRequestState) {
    NYTAdRequestStateInactive,
    NYTAdRequestStateLoading
};

ビットマスク

ビットマスクを使う際、NS_OPTIONSマクロを使うこと。

良い例:

typedef NS_OPTIONS(NSUInteger, NYTAdCategory) {
  NYTAdCategoryAutos      = 1 << 0,
  NYTAdCategoryJobs       = 1 << 1,
  NYTAdCategoryRealState  = 1 << 2,
  NYTAdCategoryTechnology = 1 << 3
};

プライベートプロパティ

プライベートプロパティは実装ファイルのクラス拡張に書き、カテゴリ名を空にすること。

良い例:

@interface NYTAdvertisement ()

@property (nonatomic, strong) GADBannerView *googleAdView;
@property (nonatomic, strong) ADBannerView *iAdView;
@property (nonatomic, strong) UIWebView *adXWebView;

@end

画像ファイル名

画像ファイル名は一貫した名前をつけること。キャメルケースで目的名、続いて接頭語無しのクラス名やプロパティ名、続いて色名や位置名、最後に状態名という名前にする。

良い例:

  • RefreshBarButtonItem / RefreshBarButtonItem@2xRefreshBarButtonItemSelected / RefreshBarButtonItemSelected@2x
  • ArticleNavigationBarWhite / ArticleNavigationBarWhite@2xArticleNavigationBarBlackSelected / ArticleNavigationBarBlackSelected@2x.

ImagesフォルダやAsset Catalogに同じ目的の画像をグループで分ける。

ブーリアン

YESと直接比較しないこと。なぜならYES1と定義されていて、Objective-CのBOOLは8ビット長のCHAR型のため(そのため11111110YESと比較したらNOが返る)。

オブジェクトポインタの良い例:

if (!someObject) {
}

if (someObject == nil) {
}

BOOL値の良い例:

if (isAwesome)
if (!someNumber.boolValue)
if (someNumber.boolValue == NO)

悪い例:

if (isAwesome == YES) // 決してしないこと。

BOOLプロパティ名が形容詞なら、isプレフィックスが省略可だがゲッター名にて指定するように。

良い例:

@property (assign, getter=isEditable) BOOL editable;

テキストと例はCocoa命名ガイドラインより引用。

シングルトン

スレッドセーフパターンでシングルトンを作成するように。

+ (instancetype)sharedInstance {
   static id sharedInstance = nil;

   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
      sharedInstance = [[[self class] alloc] init];
   });

   return sharedInstance;
}

これにより、クラッシュの可能性を避けることができます。

インポート

インポート文が複数ある場合、グループにすること。それぞれのグループにコメントしてもよい。

注意:モジュールには@import構文を使うこと。

// Frameworks
@import QuartzCore;

// Models
#import "NYTUser.h"

// Views
#import "NYTButton.h"
#import "NYTUserView.h"

Xcode プロジェクト

Xcodeのグループとプロジェクトのフォルダが同じようにして分かりやすくすること。型でグループするだけではなく、機能ごとにグループするように。

できれば、targetのBuild Settingsの“Treat Warnings as Errors“をオンにし、多めにアディショナルワーニング をオンにする。特定のワーニングをオフしたい場合、Clang's pragma機能を使うように。

他のObjective-Cスタイルガイド

もし我々のスタイルガイドが合わない場合、他のスタイルガイドをチェックしてみてください。