Objective-CおよびCocoaを作成するときに使用するベストプラクティスは何ですか? [閉まっている]
-
03-07-2019 - |
質問
HIG (これは非常に便利です!)、Objective-Cを記述するとき、より具体的にはCocoa(またはCocoaTouch)を使用するとき、どのプログラミング手法を使用します。
解決
標準的なものとは思わない、私が始めたいくつかのことがあります:
1)プロパティの出現により、「_」を使用しなくなりました。 「プライベート」の前に付けるクラス変数。結局のところ、他のクラスが変数にアクセスできる場合、そのプロパティはありませんか?私はいつも" _"が嫌いだったコードをlierくするための接頭辞、そして今私はそれを省くことができます。
2)プライベートなことについて言えば、プライベートメソッド定義を.mファイル内の次のようなクラス拡張子に配置することを好みます。
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
.hファイルを、部外者が気にする必要のないもので混乱させるのはなぜですか? empty()は、.mファイルのプライベートカテゴリに対して機能し、宣言されたメソッドを実装しない場合、コンパイル警告を発行します。
3).allocファイルを@synthesizeディレクティブのすぐ下に配置しました。割り当て解除したものが、クラスで考えたいことのリストの一番上にあるべきではありませんか? iPhoneのような環境では特にそうです。
3.5)テーブルセルでは、パフォーマンスのためにすべての要素(セル自体を含む)を不透明にします。つまり、すべてに適切な背景色を設定することを意味します。
3.6)NSURLConnectionを使用する場合、ルールとしてデリゲートメソッドを実装することをお勧めします。
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
ほとんどのWeb呼び出しは非常に特異であり、特にWebサービス呼び出しの場合、応答をキャッシュするルールよりも例外です。示されているようにメソッドを実装すると、応答のキャッシュが無効になります。
興味深いのは、Joseph Mattiello(iPhoneメーリングリストで受け取った)からのiPhone固有の良いヒントです。他にもありますが、これらは私が考えた最も一般的に有用なものでした(応答で提供される詳細を含めるために、オリジナルからいくつかのビットが少し編集されていることに注意してください):
4)CoreLocationを使用する場合など、必要な場合にのみ倍精度を使用します。定数を 'f'で終了して、gccがそれらをfloatとして保存するようにしてください。
float val = someFloat * 2.2f;
これは、 someFloat
が実際にdoubleである場合に最も重要です。ストレージの 'val'の精度が失われるため、混合モードの数学は必要ありません。 iPhoneのハードウェアでは浮動小数点数がサポートされていますが、単精度ではなく倍精度の計算を行うにはさらに時間がかかる場合があります。参照:
古い携帯電話では、計算は同じ速度で動作すると思われますが、レジスタ内の倍精度よりも単精度のコンポーネントを増やすことができるため、多くの計算では単精度が高速になります。
5)プロパティを nonatomic
として設定します。デフォルトでは atomic
であり、合成時に、マルチスレッドの問題を防ぐためにセマフォコードが作成されます。おそらく99%はこれについて心配する必要はなく、コードは非アトミックに設定されていると、コードの肥大化が少なくなり、メモリ効率が向上します。
6)SQLiteは、大きなデータセットをキャッシュする非常に高速な方法です。たとえば、マップアプリケーションは、タイルをSQLiteファイルにキャッシュできます。最も高価な部分はディスクI / Oです。大きなブロック間で BEGIN;
および COMMIT;
を送信することにより、多くの小さな書き込みを避けます。新しい送信ごとにリセットされる2秒のタイマーを使用します。有効期限が切れると、COMMITを送信します。 、すべての書き込みが1つの大きな塊になります。 SQLiteはトランザクションデータをディスクに保存し、このBegin / Endラッピングを行うことで、多くのトランザクションファイルの作成を回避し、すべてのトランザクションを1つのファイルにグループ化します。
また、メインスレッド上にある場合、SQLはGUIをブロックします。非常に長いクエリがある場合は、クエリを次のように保存することをお勧めします
他のヒント
不明な文字列をフォーマット文字列として使用しないでください
メソッドまたは関数がフォーマット文字列の引数を取る場合、フォーマット文字列の内容を制御できることを確認する必要があります。
たとえば、文字列をログに記録する場合、文字列変数を NSLog
への唯一の引数として渡すことは魅力的です:
NSString *aString = // get a string from somewhere;
NSLog(aString);
これに関する問題は、文字列にフォーマット文字列として解釈される文字が含まれている可能性があることです。これは、誤った出力、クラッシュ、およびセキュリティの問題につながる可能性があります。代わりに、文字列変数をフォーマット文字列に置き換える必要があります。
NSLog(@"%@", aString);
他の環境で慣れ親しんでいるものではなく、標準のCocoa命名およびフォーマットの規則と用語を使用します。そこには 多くのCocoa開発者がいますが、他のCocoa開発者があなたのコードを使い始めたとき、他のCocoaコードと同じように見えると感じれば、より親しみやすくなります。
何をすべきか、何をすべきでないかの例:
- オブジェクトのインターフェースで
id m_something;
を宣言せずに、 member variable または field と呼びます。名前にsomething
または_something
を使用し、インスタンス変数と呼びます。 - ゲッターに
-getSomething
という名前を付けないでください。適切なCocoa名は単なる-something
です。 - セッターに名前を付けない
-something:
;-setSomething:
である必要があります
- メソッド名には引数が散在し、コロンが含まれます。
-[NSObject performSelector:withObject:]
であり、NSObject :: performSelector
ではありません。 - アンダーバー(アンダースコア)ではなく、メソッド名、パラメーター、変数、クラス名などにインターキャップ(キャメルケース)を使用します。
- クラス名は大文字で始まり、変数名とメソッド名は小文字で始まります。
他に何をするにしても、 Win16 / Win32スタイルのハンガリー語表記を使用しない。 Microsoftでさえ、.NETプラットフォームへの移行をあきらめました。
IBOutlets
従来、アウトレットのメモリ管理は貧弱でした。 現在のベストプラクティスは、アウトレットをプロパティとして宣言することです。
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
プロパティを使用すると、メモリ管理のセマンティクスが明確になります。また、インスタンス変数合成を使用する場合、一貫したパターンを提供します。
LLVM / Clang Static Analyzerを使用
注:Xcode 4では、これは現在IDEに組み込まれています。
Clang Static Analyzer を使用して、当然ながらCとObjectiveを分析します。 Mac OS X 10.5の-Cコード(まだC ++なし)。インストールして使用するのは簡単です:
- このページから最新バージョンをダウンロードします。
- コマンドラインから、
cd
をプロジェクトディレクトリに移動します。 -
scan-build -k -V xcodebuild
を実行します。
(追加の制約などがあります。特に、「デバッグ」構成でプロジェクトを分析する必要があります。 http://clang.llvm.org/StaticAnalysisUsage.html で詳細を確認できます-しかし、それは多かれ少なかれ要約しています。)
アナライザは、メモリ管理およびコンパイラが検出できないその他の基本的な問題を示すWebページのセットを生成します。
これは微妙なものですが、便利なものです。自分を別のオブジェクトのデリゲートとして渡す場合は、 dealloc
を実行する前にそのオブジェクトのデリゲートをリセットしてください。
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
これを行うことで、デリゲートメソッドが送信されないようにします。 dealloc
を行おうとしており、エーテルの中に姿を消しているので、誤ってメッセージが送信されないようにする必要があります。 self.someObjectは別のオブジェクト(シングルトンまたは自動解放プールなど)によって保持される可能性があり、「メッセージの送信を停止してください」と言うまでは、これからのことを考えます割り当て解除されたオブジェクトは公正なゲームです。
この習慣を身に付けると、デバッグするのが面倒な多くの奇妙なクラッシュからあなたを救います。
同じプリンシパルがKey Value Observation、およびNSNotificationsにも適用されます。
編集:
さらに防御的な変更:
self.someObject.delegate = NULL;
into:
if (self.someObject.delegate == self)
self.someObject.delegate = NULL;
@kendell
代わりに:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
使用:
@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end
Objective-C 2.0の新機能。
クラスの拡張機能については、AppleのObjective-C 2.0リファレンスで説明されています。
"クラス拡張により、プライマリクラス@interfaceブロック以外の場所でクラスに追加の必要なAPIを宣言できます
したがって、これらは実際のクラスの一部であり、クラスに加えて(プライベート)カテゴリではありません。微妙だが重要な違い。
自動リリースを避ける
通常(1)存続期間を直接制御できないため、自動解放されたオブジェクトは比較的長時間持続し、アプリケーションのメモリフットプリントを不必要に増加させる可能性があります。デスクトップではこれはほとんど重要ではありませんが、より制約のあるプラットフォームではこれは重大な問題になる可能性があります。したがって、すべてのプラットフォームで、特に制約の厳しいプラットフォームでは、自動解放されたオブジェクトにつながるメソッドの使用を避けることがベストプラクティスと見なされ、代わりにalloc / initパターンを使用することをお勧めします。
したがって、以下ではなく:
aVariable = [AClass convenienceMethod];
可能な場合は、代わりに使用する必要があります:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
新しく作成されたオブジェクトを返す独自のメソッドを作成する場合、 Cocoaの命名規則により、メソッド名の前に" new"を付けて解放する必要があることを受信者に通知します。
したがって、次の代わりに:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
次のように書くことができます:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
メソッド名は" new"で始まるため、APIのコンシューマーは、受け取ったオブジェクトを解放する責任があることを知っています(たとえば、 NSObjectControllerの newObject
メソッド )。
(1)独自のローカル自動解放プールを使用して制御できます。詳細については、自動解放プール。
これらのいくつかはすでに言及されていますが、ここに私の頭の中で思い浮かぶものがあります:
- KVOの命名規則に従います。現在KVOを使用していない場合でも、私の経験では、将来的にはまだ有益であることがよくあります。また、KVOまたはバインディングを使用している場合は、想定どおりに機能していることを知る必要があります。これには、アクセサメソッドとインスタンス変数だけでなく、多対多の関係、検証、依存キーの自動通知なども含まれます。
- プライベートメソッドをカテゴリに入れます。インターフェイスだけでなく、実装も同様です。プライベートメソッドと非プライベートメソッドの間に概念的にある程度の距離を置くのは良いことです。 .mファイルにすべてを含めます。
- バックグラウンドスレッドメソッドをカテゴリに入れます。上記と同じ。メインスレッドにあるものとそうでないものを考えている場合、明確な概念上の障壁を維持するのが良いことがわかりました。
-
#pragma mark [section]
を使用します。通常、独自のメソッド、各サブクラスのオーバーライド、および情報または正式なプロトコルによってグループ化します。これにより、探しているものに簡単にジャンプできます。同じトピックで、同様のメソッド(Table Viewのデリゲートメソッドなど)をグループ化し、それらをどこにも貼り付けないでください。 - プレフィックスプライベートメソッド& ivars with _。見た目が好きで、偶然プロパティを意味するときにivarを使用する可能性は低くなります。
- initおよび&でミューテーターメソッド/プロパティを使用しないそのために悪いことは一度もありませんでしたが、オブジェクトの状態に応じて何かを行うようにメソッドを変更すると、ロジックを見ることができます。
- プロパティにIBOutletsを挿入します。実際にここでこれを読みましたが、これから始めます。メモリの利点に関係なく、スタイル的には(少なくとも私には)より良いようです。
- 絶対に必要ではないコードを書くことを避けます。これは、
#define
が実行するときにivarを作成したり、代わりに配列をキャッシュするなど、多くのことをカバーします。データが必要になるたびに並べ替えます。私はこれについて多くのことを言うことができますが、一番下の行はあなたがそれを必要とするかプロファイラーがあなたに言うまでコードを書かないことです。長期的に物事を維持するのがずっと簡単になります。 - 開始したものを終了します。バグの多い中途半端なコードは、プロジェクトの死者を殺すための最速の方法です。問題のないスタブメソッドが必要な場合は、
NSLog(@" stub")
を内部に配置するか、物事を追跡したい場合にそれを示すだけです。
単体テストを記述します。他のフレームワークでは難しいかもしれないCocoaのたくさんのをテストできます。たとえば、UIコードを使用すると、通常は物事が本来あるべき状態に接続されていることを確認し、使用時に機能することを信頼できます。そして、状態と設定をセットアップできます。デリゲートメソッドを簡単に呼び出してテストします。
また、パブリックメソッド、プロテクトメソッド、プライベートメソッドの可視性がないため、内部のテストを作成する際の邪魔になりません。
ゴールデンルール: alloc
を実行すると、 release
!
更新:ARCを使用していない場合
Objective-CをJava / C#/ C ++ / etcのように記述しないでください。
以前、Java EE Webアプリケーションの作成に慣れていたチームがCocoaデスクトップアプリケーションを作成しようとしたことがありました。 Java EE Webアプリケーションであるかのように。本当に必要なのはFooクラスと、おそらくFooableプロトコルだけでしたが、AbstractFooFactoryとFooFactory、IFooとFooが飛び回っていました。
これを行わないようにすることの一部は、言語の違いを真に理解することです。たとえば、Objective-Cクラスのメソッドはインスタンスメソッドと同じように動的にディスパッチされ、サブクラスでオーバーライドできるため、上記の抽象ファクトリおよびファクトリクラスは必要ありません。
マジックのデバッグページをブックマークしてください。これは、Cocoaバグの原因を見つけようとしているときに頭を壁にぶつけたときの最初の目的地です。
たとえば、最初にメモリを割り当てたメソッドを見つける方法を教えてくれます(後でアプリの終了時など)。
ユーザーが望むように文字列をソート
文字列を並べ替えてユーザーに提示するときは、単純な compare:
メソッドを使用しないでください。代わりに、 localizedCompare:
や localizedCaseInsensitiveCompare:
などのローカライズされた比較メソッドを常に使用する必要があります。
詳細については、検索、比較、並べ替えをご覧ください。文字列。
私が今、Newbiecategoryaholismと呼ぶことにしたことを避けるようにしてください。 Objective-Cの初心者がカテゴリを発見すると、既存のすべてのクラスに便利な小さなカテゴリを追加します(" What?私は、数値をローマ数字に変換するメソッドをNSNumberに変換できます!" )。
これをしないでください。
コードはより移植性が高く、簡単に理解できるようになります。2ダースの基礎クラスの上に何十もの小さなカテゴリメソッドが散在しています。
ほとんどの場合、コードを合理化するためにカテゴリメソッドが必要であると本当に考える場合、メソッドを再利用することはありません。
他の危険もあります。カテゴリメソッドに名前空間を付けていない限り(そして、非常に非常識なddribin以外は誰ですか?)、Apple、プラグイン、またはアドレススペースで実行されている何かが定義する可能性がありますわずかに異なる副作用を持つ同じ名前の同じカテゴリメソッド...
OK。警告が表示されたので、「この部分を実行しない」を無視してください。ただし、極度に抑制してください。
世界のサブクラス化に抵抗します。 Cocoaでは、他のフレームワークではサブクラス化により行われる、基になるランタイムの委任と使用により多くのことが行われます。
たとえば、Javaでは匿名の * Listener
サブクラスのインスタンスを多く使用し、.NETでは EventArgs
サブクラスを多く使用します。 Cocoaでは、どちらも—しません。代わりにtarget-actionが使用されます。
宣言されたプロパティ
通常は、すべてのプロパティに対してObjective-C 2.0宣言プロパティ機能を使用する必要があります。パブリックでない場合は、クラス拡張に追加します。宣言されたプロパティを使用すると、メモリ管理のセマンティクスがすぐに明確になり、deallocメソッドを簡単に確認できます。プロパティ宣言をグループ化すると、それらをすばやくスキャンしてdeallocメソッドの実装と比較できます。
プロパティを「非アトミック」としてマークしない前に、よく考える必要があります。 Objective Cプログラミング言語ガイドの注意事項として、プロパティはデフォルトではアトミックであり、かなりのオーバーヘッドが発生します。さらに、すべてのプロパティをアトミックにするだけでは、アプリケーションがスレッドセーフになりません。もちろん、「nonatomic」を指定せず、独自のアクセサメソッドを(それらを合成するのではなく)実装しない場合は、アトミックに実装する必要があることに注意してください。
nil値について考える
この質問のメモ、 nil
へのメッセージObjective-Cでは有効です。これはしばしば利点であり、よりクリーンでより自然なコードにつながりますが、この機能は、 nil
の値を取得していない場合に、特異で追跡が困難なバグを引き起こす可能性があります。それを期待していません。
NSAssertとフレンドを使用します。 私は常にnilを有効なオブジェクトとして使用しています...特にnilへのメッセージ送信はObj-Cでは完全に有効です。 ただし、変数の状態について本当に確認したい場合は、NSAssertとNSParameterAssertを使用します。これにより、問題を簡単に追跡できます。
シンプルだが忘れられがちなもの。仕様によると:
一般に、異なる方法 同じセレクターを持つクラス (同じ名前)も共有する必要があります 同じ戻り値と引数のタイプ。この コンパイラによって制約が課されます 動的バインディングを許可します。
この場合、すべての同じ名前のセレクターは、異なるクラスであっても、同一の戻り値/引数タイプを持つと見なされます。以下に簡単な例を示します。
@interface FooInt:NSObject{}
-(int) print;
@end
@implementation FooInt
-(int) print{
return 5;
}
@end
@interface FooFloat:NSObject{}
-(float) print;
@end
@implementation FooFloat
-(float) print{
return 3.3;
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
id f1=[[FooFloat alloc]init];
//prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
NSLog(@"%f",[f1 print]);
FooFloat* f2=[[FooFloat alloc]init];
//prints 3.3 expectedly as the static type is FooFloat
NSLog(@"%f",[f2 print]);
[f1 release];
[f2 release]
[pool drain];
return 0;
}
Leopard(Mac OS X 10.5)以降を使用している場合、Instrumentsアプリケーションを使用してメモリリークを検出および追跡できます。 Xcodeでプログラムをビルドした後、[実行]>を選択します。パフォーマンスツールから開始>リーク。
アプリにリークが表示されない場合でも、オブジェクトを長くしすぎている可能性があります。機器では、このためにObjectAlloc機器を使用できます。 InstrumentsドキュメントでObjectAllocインストゥルメントを選択し、View>を選択して、インストゥルメントの詳細を表示します(まだ表示されていない場合)。詳細(横にチェックマークが必要です)。 [割り当ての有効期間]の下でObjectAllocの詳細で、" Created&の隣のラジオボタンを選択していることを確認してください。まだ生きています。
アプリケーションの記録を停止するたびに、ObjectAllocツールを選択すると、「#ネット」にあるアプリケーション内のまだ生きているオブジェクトへの参照の数が表示されます。カラム。独自のクラスだけでなく、NIBファイルのトップレベルオブジェクトのクラスも確認してください。たとえば、画面にウィンドウがなく、まだ生きているNSWindowへの参照が表示されている場合、コードでそれを解放していない可能性があります。
deallocでクリーンアップします。
これは忘れがたい最も簡単なものの1つです。 150mphでコーディングする場合。常に、常に、deallocの属性/メンバー変数を常にクリーンアップします。
Objc 2属性を使用するのが好きです-新しいドット表記で -これにより、クリーンアップが簡単になります。多くの場合、次のように簡単です:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
これにより、リリースが処理され、属性がNULLに設定されます(これは防御的プログラミングと見なされます-deallocでさらに下の別のメソッドが再びメンバー変数にアクセスする場合-まれですが、できます )。
10.5でGCをオンにすると、これはそれほど必要ではなくなりますが、作成した他のリソースをクリーンアップする必要がある場合は、代わりにfinalizeメソッドでそれを行うことができます。
これらのコメントはすべて素晴らしいですが、 Googleの誰も言及していないことに本当に驚いていますしばらく前に公開されたObjective-Cスタイルガイド。彼らは非常に徹底した仕事をしたと思います。
また、半関連のトピック(より多くの応答の余地がある!):
NSWindowControllerとNSViewControllerが、管理しているNIBファイルの最上位オブジェクトを解放することを忘れないでください。
NIBファイルを手動でロードする場合、NIBの作業が完了したら、NIBの最上位オブジェクトを解放する責任があります。
初心者が使用するかなり明らかなもの:コードにXcodeの自動インデント機能を利用します。別のソースからコピー/貼り付けしている場合でも、コードを貼り付けたら、コードのブロック全体を選択して右クリックし、そのブロック内のすべてを再度インデントするオプションを選択できます。
Xcodeは実際にそのセクションを解析し、ブラケット、ループなどに基づいてインデントします。すべての行でスペースバーまたはタブキーを押すよりもはるかに効率的です。
Cocoaプログラミングを初めて使用するときに、これを見落としていたことを知っています。
NIBファイルに関するメモリ管理の責任を理解してください。ロードするNIBファイルのトップレベルオブジェクトをリリースする責任があります。 この件に関するAppleのドキュメント。
すべてのGCC警告をオンにしてから、Appleのヘッダーによって定期的に発生する警告をオフにして、ノイズを減らします。
また、Clang静的解析を頻繁に実行します。 " Run Static Analyzer"を介してすべてのビルドに対して有効にすることができます。ビルド設定。
ユニットテストを作成し、ビルドごとに実行します。
変数とプロパティ
1 /ヘッダーをクリーンに保ち、実装を隠します
ヘッダーにインスタンス変数を含めないでください。プライベート変数は、プロパティとしてクラス継続に配置されます。パブリック変数は、ヘッダーのパブリックプロパティとして宣言します。
読み取り専用にする必要がある場合は、読み取り専用として宣言し、クラス継続で読み取り書き込みとして上書きします。
基本的に、私は変数をまったく使用せず、プロパティのみを使用しています。
2 /プロパティにデフォルト以外の変数名を付けます。例:
@synthesize property = property_;
理由1:" self。"を忘れることによって引き起こされるエラーをキャッチします。プロパティを割り当てるとき。 理由2:私の実験から、InstrumentsのLeak Analyzerには、デフォルトの名前で漏れているプロパティを検出する問題があります。
3 /プロパティに対して直接、保持または解放を使用しないでください(または非常に例外的な状況でのみ)。 deallocでそれらにnilを割り当てるだけです。保持プロパティは、保持/解放を単独で処理するためのものです。セッターが、たとえばオブザーバーの追加または削除ではないかどうかはわかりません。変数はそのセッターとゲッター内でのみ直接使用する必要があります。
ビュー
1 /可能であれば、すべてのビュー定義をxibに配置します(通常、例外は動的コンテンツとレイヤー設定です)。時間を節約し(コードを書くよりも簡単です)、変更が簡単で、コードをクリーンに保ちます。
2 /ビューの数を減らしてビューを最適化しようとしないでください。サブビューを追加したいという理由だけで、コードにxibの代わりにUIImageViewを作成しないでください。代わりにUIImageViewを背景として使用してください。ビューフレームワークは何百ものビューを問題なく処理できます。
3 / IBOutletsは常に保持する(または強力にする)必要はありません。 IBOutletsのほとんどはビュー階層の一部であり、したがって暗黙的に保持されることに注意してください。
4 / viewDidUnloadのすべてのIBOutletsをリリースします
5 / deallocメソッドからviewDidUnloadを呼び出します。暗黙的に呼び出されることはありません。
メモリ
1 /作成時にオブジェクトを自動解放します。多くのバグは、リリースコールを1つのif-elseブランチに移動したか、returnステートメントの後に発生します。自動リリースではなくリリースは、例外的な状況でのみ使用する必要があります。ランループを待っているときに、オブジェクトを早く自動リリースしたくない場合。
2 / Authomatic Reference Countingを使用している場合でも、リテンションリリースメソッドの仕組みを完全に理解する必要があります。リテインリリースを手動で使用することはARCより複雑ではありません。どちらの場合も、リークとリテインサイクルについて注意する必要があります。 大きなプロジェクトや複雑なオブジェクト階層でリテンションリリースを手動で使用することを検討してください。
コメント
1 /コードを自動文書化します。 すべての変数名とメソッド名は、それが何をしているかを伝える必要があります。コードが正しく記述されている場合(これには多くの練習が必要です)、コードコメント(ドキュメンテーションコメントとは異なります)は必要ありません。アルゴリズムは複雑になる可能性がありますが、コードは常に単純でなければなりません。
2 /場合によっては、コメントが必要になります。通常、明らかでないコードの動作またはハッキングを記述します。コメントを書く必要があると思う場合は、最初にコードを書き直して、コメントを必要としないようにしてください。
インデント
1 /インデントを大きくしすぎないでください。 メソッドコードのほとんどは、メソッドレベルでインデントする必要があります。ネストされたブロック(if、forなど)は可読性を低下させます。ネストされたブロックが3つある場合、内側のブロックを別のメソッドに配置する必要があります。 4つ以上のネストされたブロックは使用しないでください。 メソッドコードのほとんどがif内にある場合、if条件を否定します。例:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
Cコード、主にC構造体を理解する
Obj-Cは、C言語上の軽いOOPレイヤーにすぎないことに注意してください。 Cの基本的なコード構造(enum、構造体、配列、ポインターなど)の仕組みを理解する必要があります。 例:
より機能的になります。
Objective-Cはオブジェクト指向言語ですが、Cocoaフレームワークの機能スタイルに対応しており、多くの場合、機能スタイルが設計されています。
-
可変性の分離があります。 immutable クラスをプライマリとして使用し、可変オブジェクトをセカンダリとして使用します。たとえば、主にNSArrayを使用し、必要な場合にのみNSMutableArrayを使用します。
-
純粋な関数があります。フレームワークAPIの多くを購入することは、純粋な機能のように設計されています。
CGRectMake()
やCGAffineTransformMake()
などの関数を見てください。明らかに、ポインタ形式はより効率的に見えます。ただし、ポインターを使用した間接引数は、副作用なしで提供できません。構造をできるだけ純粋に設計します。 偶数の状態オブジェクトを分離します。他のオブジェクトに値を渡すときは、-retain
の代わりに-copy
を使用します。共有状態は、他のオブジェクトの値への変換にサイレントに影響を与える可能性があるためです。したがって、副作用がないことはできません。オブジェクトの外部からの値がある場合は、それをコピーします。したがって、共有状態を可能な限り最小限に設計することも重要です。
ただし、不純な関数も使用することを恐れないでください。
-
遅延評価があります。
-[UIViewController view]
プロパティのようなものを参照してください。オブジェクトが作成されるとき、ビューは作成されません。呼び出し元が最初にview
プロパティを読み取るときに作成されます。UIImage
は、実際に描画されるまでロードされません。この設計のような多くの実装があります。この種の設計はリソース管理に非常に役立ちますが、遅延評価の概念がわからない場合、それらの動作を理解することは容易ではありません。 -
閉鎖があります。可能な限りCブロックを使用します。これにより、人生が大幅に簡素化されます。ただし、使用する前にブロックメモリ管理についてもう一度お読みください。
-
セミオートGCがあります。 NSAutoreleasePool。プライマリ
-autorelease
を使用します。本当に必要な場合は、手動で-retain / -release
セカンダリを使用します。 (例:メモリの最適化、明示的なリソースの削除)