4

私はいつも、すべてのアップル コード サンプルが次のようなコードを使用する理由を疑問に思っていました。

UINavigationController *aNavigationController = [[UINavigationController alloc]
          initWithRootViewController:rootViewController];

self.navigationController = aNavigationController;

[self.view addSubview:[navigationController view]];

[aNavigationController release];

彼らは常にローカル変数を作成し、それをivarに割り当てます。単純にこれをしないのはなぜですか:

self.navigationController = [[UINavigationController alloc]
          initWithRootViewController:rootViewController];;

[self.view addSubview:[navigationController view]];

[navigationController release];

分かりやすいという以外に何か理由はありますか?これはベスト プラクティスですか。

-オスカー

4

5 に答える 5

2

交換用コードが間違っているため、Apple が防止しようとしている問題が示されています。コードは次のとおりです。

self.navigationController = [[UINavigationController alloc]
      initWithRootViewController:rootViewController];

[self.view addSubview:[navigationController view]];

[navigationController release];

あなたは「自分」を省きました。あなたの参照で。ivar に直接アクセスするつもりだったのかもしれませんが、その場合は、アクセサーと ivar への直接アクセスを混在させて、非常に紛らわしいコードを作成してしまいました (また、アクセサーの外部で ivar への直接アクセスを使用することで基本規則に違反しました)。そうでない場合は、これを書くつもりでした:

self.navigationController = [[UINavigationController alloc]
      initWithRootViewController:rootViewController];

[self.view addSubview:[self.navigationController view]];

[self.navigationController release];

その最後の行は非常に間違っています。メソッド呼び出しの結果に -release を送信しないでください。いいえ、あなたのやり方は正しくありません。

とはいえ、Apple と私はこれを行う方法について意見が分かれています。これが私がそれを行う方法です:

self.navigationController = [[[UINavigationController alloc]
      initWithRootViewController:rootViewController] autorelease;

[self.view addSubview:[self.navigationController view]];

-autorelease が好きなのは、エラーを防ぐことができるからです。alloc と release が離れれば離れるほど、開発者はメモリ リークを挿入する可能性が高くなります (たとえば、"return" を追加することによって)。autorelease は、retain と release を一緒に保つことでこれを回避し、これを一時変数として使用する意図をより明確にし、一般的にコード レビューをより簡単にします。

Apple は、リリース対自動リリースを使用してパフォーマンスを強調しているため、コード例で私に反対する傾向があります。どちらの場合も、この実行ループ中にこのオブジェクトの割り当てが解除されないため (メモリが節約されないため)、これは間違った最適化であることがわかります。 release の不適切な使用によるメモリ リークの減少。

自動リリースとリリースの議論は灰色の色合いでいっぱいです (私は確かにリリースをループで直接使用しています)。開発者によってアプローチは異なりますが、どちらの場合も、置換コードは正しい方法ではありません。

于 2010-02-05T23:07:26.520 に答える
1

どちらのバージョンも nil 値のチェックを欠いています:

(self.navigationController がその値を保持するプロパティであると仮定します)

self.navigationController = [[UINavigationController alloc]
    initWithRootViewController:rootViewController];
if (self.navigationController != nil) {
    [self.view addSubview: navigationController.view;
    [self.navigationController release];
}

これはスタイルだと主張することもできますが、私の意見では、バグの少ないコードにつながります。

于 2010-02-05T22:41:41.930 に答える
1

上の例と同じかもしれませんが、そうではない可能性があります。

覚えておいてください

self.navigationController = aNavigationController;

と同じです

[self setNavigationController:aNavigationController];

setNavigationControllerそのメソッドの中で何が起こっているのかわかりません。別のオブジェクトを初期化し、それを iVar として設定してから解放すると、クラッシュが発生する可能性があります。

于 2010-02-05T22:42:49.153 に答える
1

最初の行の違いは、Apple のバージョンではオブジェクトの作成と ivar への割り当てが分離されているのに対し、あなたのバージョンでは 2 つが一緒になっていることです。概念的には、Apple のバージョンの方が若干理解しやすいです。私の知る限り、これはベストプラクティスではありません。

于 2010-02-05T22:37:32.823 に答える
0

コードが UINavigationController インスタンス変数を使用していることは明らかです。その場合、次のことを行う理由はありません。

self.navigationController = aNavigationController

守らないと。

しかし、次のようにすると:

 self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

その後、次のようにリリースすると:

[navigationController release];

ナビゲーション コントローラを初期化する現在のクラスの存続期間中保持されるはずのインスタンス変数を解放しているように見えます。そのため、dealloc メソッドでのみリリースする必要があると初心者が考えるように、誤解されがちです。

どちらのアプローチでも、最終的に保持カウントは 0 になります。dealloc 実装の場合:

[navigationController release]; // 1 for the ivar
[super dealloc]; // 0 for the retained subviews
于 2010-02-05T23:01:15.543 に答える