web-dev-qa-db-ja.com

ARCにするかどうか長所と短所は何ですか?

私が現在取り組んでいるプロジェクトのコードの大部分はiOS 5.0より前に書かれていたため、ARCはまだ使用していません。

ARCを使用することの「コスト」よりも、手動で保持/解放しないことの利便性(および結果として、おそらくより信頼性の高いコード)を上回るのだろうかと思いました。 ARCの経験はどのようなものですか?

そう:

  • ARCはプロジェクトにどの程度の利益をもたらすことができますか?
  • ARCにはJavaのガベージコレクションのようなコストがかかりますか?
  • ARCを使用していますか?使用している場合、これまでどのように見つけましたか?
112

欠点はありません。これを使って。今日それをしてください。古いコードよりも高速です。古いコードよりも安全です。古いコードよりも簡単です。ガベージコレクションではありません。 GCランタイムのオーバーヘッドはありません。コンパイラは、保持する必要があるすべての場所にリリースを挿入します。しかし、それはあなたよりも賢く、実際に必要のないものを最適化できます(ループを展開したり、一時変数やインライン関数を削除したりできるように)。

さて、ここで小さな欠点について説明します。

  • あなたが長年のObjC開発者であれば、ARCコードを見ると約1週間Twitchをするでしょう。これはすぐに解決できます。

  • Core Foundationコードへのブリッジングには、いくつかの(非常に)小さな問題があります。 idを_void*_として扱うものを扱うと、少し複雑になります。 idのC配列のようなものは、正しく実行するためにもう少し考える必要があります。 ObjC _va_args_の高度な処理も問題を引き起こす可能性があります。 ObjCポインターでの数学を伴うほとんどのことは、より複雑です。いずれにせよ、これの多くは必要ありません。

  • idstructに入れることはできません。これはかなりまれですが、データのパックに使用されることもあります。

  • 正しいKVC命名に従わず、ARCコードと非ARCコードを混在させると、メモリの問題が発生します。 ARCはKVCネーミングを使用して、メモリ管理に関する決定を行います。それがすべてARCコードである場合、両側で同じ「間違った」ことを行うため、それは問題ではありません。ただし、ARCと非ARCが混在している場合は、不一致があります。

  • ARCは、ObjC例外のスロー中にメモリをリークします。 ObjC例外は、プログラムの終了に非常に近いはずです。かなりの数のObjC例外をキャッチしている場合、それらを誤って使用しています。これは_-fobjc-arc-exceptions_を使用して修正できますが、以下で説明するペナルティが発生します。

  • ObjCまたはC++例外がObjC++コードでスローされている間、ARCはメモリをリークしませんが、これには時間とスペースの両方のパフォーマンスが犠牲になります。これは、ObjC++の使用を最小限に抑える理由の長いリストのもう1つです。

  • ARCは、iPhoneOS 3またはMac OS X 10.5以前ではまったく機能しません。 (これにより、多くのプロジェクトでARCを使用できなくなります。)

  • ___weak_ポインターはiOS 4またはMac OS X 10.6では正しく機能しません。これは残念ですが、回避するのはかなり簡単です。 ___weak_ポインターは優れていますが、ARCの最大のセールスポイントではありません。

95%以上のコードについては、ARCは素晴らしいものであり、それを回避する理由はまったくありません(OSバージョンの制限を処理できる場合)。非ARCコードの場合、ファイルごとに_-fno-objc-arc_を渡すことができます。残念ながら、Xcodeはこれを実際に行うよりもはるかに困難にします。これを簡素化するには、おそらく非ARCコードを別のxcodeprojに移動する必要があります。

結論として、できるだけ早くARCに切り替えて、決して振り返らないでください。


[〜#〜] edit [〜#〜]

「ARCを使用することは、Cocoaのメモリ管理ルールを知ることの代わりにならない」という行に沿って、いくつかのコメントを見てきました。これはほとんど真実ですが、理由と理由を理解することが重要です。まず、すべてのコードがARCを使用していて、あらゆる場所で つのマジックワード に違反している場合でも、問題はありません。と言って衝撃的ですが、そこに行きます。 ARCは、ユーザーが保持するつもりのないものをいくつか保持する場合がありますが、それらも同様にリリースするため、問題にはなりません。今日、Cocoaで新しいクラスを教えている場合、実際のメモリ管理ルールにたった5分しかかからず、KVCの命名については、メモリ管理の命名ルールについてのみ言及するでしょう。 ARCを使用すると、メモリ管理のルールをまったく習得しなくても、実際にはまともな初心者プログラマーになることができると思います。

しかし、あなたはまともな中級プログラマーになることはできませんでした。 Core Foundationと正しくブリッジするためにはルールを知る必要があり、すべての中間プログラマーはある時点でCFに対処する必要があります。そして、ARC/MRC混合コードのルールを知る必要があります。そして、idへの_void*_ポインター(KVOを正しく実行するために引き続き必要です)をいじり始めるときのルールを知る必要があります。そして、ブロック...まあ、ブロックメモリ管理は奇妙です。

私のポイントは、基礎となるメモリ管理が依然として重要であるということですが、以前は新しいプログラマーのためにルールの記述と再記述にかなりの時間を費やしていましたが、ARCではより高度なトピックになっています。 objc_retain()の基本的な呼び出しで頭を埋めるのではなく、オブジェクトグラフの観点から新しい開発者に考えてもらいたいです。

147
Rob Napier

私のものよりも優れた技術的な答えが来るでしょうが、ここにあります:

  • ARC!=ガベージコレクション。実行時のペナルティはありません。コンパイル時に行われます。
  • また、ARCは、コメントで提案されているように、すべてを自動で解放します。 docs を読む
  • あなたがどれだけの手動参照管理をしていたかを理解したら、それは素晴らしいことです
  • これを使って!
  • 欠点の1つは、古い非アークコードの維持が突然非常に面倒になることです。
20
jrturton

ARCはプロジェクトにどの程度の利益をもたらすことができますか?

利点は、一般的なメモリ管理のミスからの大幅な保護です。オブジェクトのリリースに失敗したことによるリークと、オブジェクトの保持または早期リリースに失敗したことによるクラッシュは、大幅に減らす必要があります。参照カウントメモリモデルを理解して、参照を強弱に分類したり、保持サイクルを回避したりできるようにする必要があります。

ガベージコレクションは実際にどのくらいのコストがかかりますか?

IOSにはガベージコレクションはありません。 ARCは、オブジェクトを手動で保持または解放する必要がないという点で、GCと似ています。 GCとは異なり、ガベージコレクターはありません。保持/解放モデルは引き続き適用されます。コンパイル時に適切なメモリ管理呼び出しがコードに挿入されるだけです。

ARCを使用していますか?使用している場合、これまでどのように見つけましたか?

参照カウントに慣れている場合は少し戸惑いますが、それは慣れて、コンパイラが本当に正しいことをすることを信頼することを学ぶだけの問題です。これは、Objective-C 2.0に伴うプロパティの変更が継続しているように感じられます。これは、メモリ管理を簡素化するためのもう1つの大きなステップでした。手動のメモリ管理呼び出しがなければ、コードは少し短くなり、読みやすくなります。

ARCの唯一の問題は、古いバージョンのiOSではサポートされていないことです。そのため、採用する前にそれを考慮する必要があります。

16
Caleb

ARCは素晴らしいアイデアだと思います。 GCと比較して、ケーキを食べて食べることもできます。私は、MRCがメモリ管理にかけがえのない「規律」を課していると信じがちです。しかし、私が知っておくべき本当の問題は、オブジェクト所有権とオブジェクトグラフ(多くが指摘しているように)であり、それ自体は低レベルの参照カウントではないことに同意します。

結論として:ARCは、メモリについて気にする必要のない無料のパスではありません。これは、ストレスを引き起こし、エラーを起こしやすい反復作業を人間が回避するのに役立つツールです。したがって、マシン(この場合はコンパイラー)により適切に委任されます。

そうは言っても、私は個人的には職人であり、まだ移行していない。 Gitの使用を開始しました...

PDATE:ですから、ゲーム全体を移行しました。glライブラリが含まれており、これまでのところ問題はありません(Xcode 4.2の移行アシスタントを除く)。新しいプロジェクトを開始する場合は、それを選択してください。

4
Nicolas Miari

私が遭遇した唯一の欠点は、多くのCoreFoundation関数とデータを備えたライブラリを使用する場合です。 MRCでは、NSString*の代わりにCFStringRefを使用することを心配する必要はありませんでした。 ARCでは、2つの相互作用を指定する必要があります(基本ブリッジ?CoreFoundationオブジェクトをリリースしてARCに移動しますか?Cocoaオブジェクトを+1 CoreFoundation保持オブジェクトとして作成しますか?)また、OS Xでは、64でのみ使用可能ですビットコード(それを回避するヘッダーがありますが…)。

2
MaddTheSane

私はいくつかの(確かに小さな)プロジェクトでそれを使用しましたが、パフォーマンスと信頼性の両面で良い経験しかありません。

ちょっとした注意点として、UIを自分でコーディングしている場合、参照ループが発生しないように弱参照のdo:sとdo n't:sを学ぶ必要があるということです。デザイナーはそれをうまくやる傾向がありますGUIを使用してGUIをセットアップすると、自動的に。

2