ARCにするか、ARCしないか?長所と短所は何ですか?[閉まっている]


113

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

私はただ疑問に思っていましたが、手動で保持/解放しないことの便利さ(そして結果としておそらくより信頼性の高いコードですか?)は、ARCを使用することの「コスト」を上回りますか?ARCについてどのような経験がありますか。それをお勧めしますか?

そう:

  • ARCはプロジェクトにどのくらいのメリットをもたらしますか?
  • ARCにはJavaのガベージコレクションのようなコストがありますか?
  • ARCを使用していますか。使用している場合、それをどのように見つけましたか?

iPad / iOSにはガベージコレクションはありません。OS Xについて話していますか?
dasblinkenlight 2012年

1
申し訳ありませんが、Javaの用語をその場で使用しています。つまり、ARCを使用すると、オブジェクトを必要以上に長くメモリに保持し、しばらくしてからグループとして自動解放プールに解放できます。私が言及しているJavaのガベージコレクションと同様に、それらが後で他のオブジェクトとともに保持および解放されることのこの効果です。
Simon Withington、2012年

3
@TenementFunster、同じコード(releaseへの呼び出しを除く)の場合、ARCは非ARCコードよりも長くオブジェクトを保持しません。実際、多くの場合、あなたが持っているよりも早くリリースされます。多少遅いものはいくつかありますが、一般的なパターンを大幅に高速化して、パフォーマンスへの影響を小さくします。多くの一般的なパターン(たとえば、autoreleaseで返されたオブジェクトを保持する)の場合、文字通り、ARCが自動的に行うほど速く手で書くことはできません。
Rob Napier

1
ガベージコレクションについては、この同様の質問に対する私の回答を参照してください。Objective-Cの自動参照カウントとガベージコレクションの違いは何ですか?
ブラッド・ラーソン

回答:


147

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

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

  • 長期にわたるObjC開発者の場合、ARCコードが表示されると、約1週間はけいれんします。あなたはこれをすぐに乗り越えるでしょう。

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

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

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

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

  • ARCは、ObjC ++コードでのObjCまたはC ++例外のスロー中にメモリをリークしませんが、これは時間とスペースの両方のパフォーマンスを犠牲にします。これは、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に切り替えてください。


編集

「ARCを使用することは、Cocoaのメモリ管理ルールを知ることの代わりにはならない」というコメントを2度目にしました。これはほとんどの場合真実ですが、その理由とそうでない理由を理解することが重要です。まず、すべてのコードがARCを使用していて、3つの魔法の言葉に違反している場合いたるところに問題はありません。と言って衝撃的ですが、そこに行きます。ARCは、保持するつもりでなかったいくつかのことを保持する可能性がありますが、それらも解放するため、重要ではありません。今日、Cocoaで新しいクラスを教えているとしたら、実際のメモリ管理規則に費やす時間は5分以内であり、KVCの命名については、メモリ管理の命名規則についてのみ言及するでしょう。ARCがあれば、メモリ管理のルールをまったく学ばなくても、まともな初心者プログラマになることができると思います。

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

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


3
非常に注意する必要があるのは(非ARCでも同様ですが、ARCでは現在では見えなくなっているため)保持サイクルです。ここでの私のアドバイスは、1)objcブロックをインスタンス変数として保存している場合、それを長時間にわたって精査し、それがivarであるオブジェクトを間接的にもキャプチャできるかどうかを確認します。2)実際にオブジェクトグラフを作成するだけでなく、実際に設計する。優れたコードを記述したい場合は、何が何を所有しているかを知る必要あります。3)使用heapshots:friday.com/bbum/2010/10/17/...
Catfish_Man

1
@Catfish_Manすべての良い点。保持ループは常に問題でした。Appleの新しいアドバイスは、#2で述べたとおりです。保持して解放するのではなく、オブジェクトグラフについて考える必要があります。#1はブロックに関する深刻な問題であり、私がブロックを見つけるいくつかの理由の1つは、慎重に対処する必要がある混合の祝福です。
Rob Napier

2
言及されていない重大な欠点が1つあります。それは、相互互換性です。クロスプラットフォームプログラミングとして知られている荒れ地に直面している勇敢で愚かな魂にとって、少なくともGNUがObjCランタイムとコンパイラー機能を拡張するまで、ARCは選択肢になりません(さらに多くのものが進んでいると言われています)。
Rabbit

2
iOS 3.xデバイスをサポートする必要がある場合を除いて、ARCを使用できます。ところで、移行を行うにはXcodeを使用してください(編集>リファクタリング> Objective-C ARCに変換)。プロセス中に、Xcodeはコードが機能することを確認し、それらの設計ガイドラインに違反するコードを見つけるために、多くの検証を行います。
ZhangChn 2012年

1
優れている..個別に答える。それは私から100番目です。1世紀おめでとう;)
Ajay Sharma

20

私よりも優れた、より技術的な答えが得られますが、ここに行きます:

  • ARC!=ガベージコレクション。実行時のペナルティはありません。コンパイル時に行われます。
  • ARCも!=コメントで提案したように、すべてを自動的に解放します。ドキュメントを読む
  • あなたはどのくらいのマニュアルの参照管理を実現一度それは素晴らしいですし、やって
  • これを使って!
  • 1つの欠点-古い非アークコードを維持することは、突然非常に退屈になります。

ええ、それが私がこれまで使用しなかった理由です-変換するために既存の大量のコードを実行する必要があるかどうかはわかりませんが、次のプロジェクトで間違いなく試してみるつもりです。答えてくれてありがとう:)
Simon Withington

古いコードを維持するのが難しくなるのではなく、期待が変わったのです。したがって、生活を楽にするためにARCを非難することは、実際には公平ではありません。Xcodeを使用すると、準備ができたときに古いコードをARCに簡単に変換できますが、古いiOSバージョンをサポートする必要がある場合は、明らかにそれを使用できません。
Caleb

1
@Caleb私はARCを非難していませんでした。それは、これまでに見た唯一の欠点です-単一のプロジェクトのスペースで私を腐らせてしまいました。
jrturton 2012年

うん。私はそれを問題として挙げていませんが、コードベースを切り替える必要があるときにメモリ管理の実践から抜け出すという小さな問題があります。私のプロジェクトの一部は10.4で実行されているため、Objective-C 1.0の作業を数多く行っています(ARCはもちろん、@ synthesizeもありません)。しかし、モードの切り替えにはかなり慣れています。
Rob Napier

@jrturton私は、OPと、ARCの機能を理解していない可能性がある将来の読者のために、それを書いたことをより明確にすべきでした。ARCとARC以外のコードを混在させると問題が発生するという誤った結論をだれにも引き出させたくなかっただけです。
Caleb

16

ARCはプロジェクトにどのくらいのメリットをもたらしますか?

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

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

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

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

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

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


1
私が話していたより良い答えがあります!
jrturton 2012年

1
ええ、素晴らしい答えです。それで、ARCが機能することを信頼することを学ぶ必要があることを除けば、ARCに本当に欠点はありませんか?その場合本当であるには余りにも良いように思われますか?
Simon Withington、2012年

4

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

結論として:ARCは、メモリについて気にしない自由なパスではありません。これは、ストレスを引き起こし、エラーが発生しやすい反復作業を回避するためのツールであるため、マシン(この場合はコンパイラ)に委任する方が適切です。

そうは言っても、私は職人のようなもので、まだ移行はしていません。Gitを使い始めたばかりです...

更新:私はゲーム全体を移行し、glライブラリを含めて、今のところ問題はありません(Xcode 4.2の移行アシスタントを除く)。あなたが新しいプロジェクトを始めているなら、それのために行ってください。


2

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

マイナーな注意事項の1つは、UIを自分でコーディングしている場合に参照ループを引き起こさないように、弱参照のdo:sとnot:sを学ぶ必要があることです。デザイナーはそれをうまく行う傾向があります。それを使用してGUIを設定すると、自動的に。


2

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.