3

アプリのリリース ビルドでのみ発生し、デバッグ ビルドでは発生しないバグを追跡するのが困難でした。ビルド間の関連する違いは、デバッグ ビルドはコンパイラの最適化なしでコンパイルされたのに対し、リリース ビルドはコンパイラの最適化を使用してコンパイルされたことであることが判明しました-O(バグは他のすべての最適化設定でも再現可能でした)。これはすべてLLVM上にあります。

私のView Controllerには、次のようにself.basicInfoContainerView定義されたプロパティがあります。

@property (weak, nonatomic) IBOutlet UIView *basicInfoContainerView;

次に、あるビューからサブビューを削除し、別のビューに追加しました。

[self.basicInfoContainerView removeFromSuperview];
[self.infoTextView addSubview:self.basicInfoContainerView];

コンパイラの最適化レベルに応じて、さまざまなことが起こりました。

最適化がオンの場合: ビューがスーパービューから削除されるとすぐに、ビューの割り当てが解除self.basicInfoContainerViewされてゼロになり、その結果、新しいビューにサブビューとして追加されませんでした。

最適化がオフの場合: サブビューはすぐに割り当て解除されず、サブビューとして新しいビューに正常に追加されました。

(プロパティ ストレージ修飾子を に変更するstrongと、ビューは両方のケースで存続しましたが、それでも問題は解決しましたが、それは私の質問ではありません。)

ここで実際に何が起こっているのかを理解するのを手伝ってくれる人が欲しい. weakコンパイラの最適化がオフになっていると、ビューがすぐに解放されない (保持カウント == 0 の場合はポインターがゼロにならない) のはなぜですか?

4

1 に答える 1

2

オブジェクトへの余分なローカル (および強力な) 参照を保持する、最適化されていないコードを目にすることは、本当に珍しいことではありません。したがって、最適化されていないコードには、この「basicInfoContainerView」へのローカルの強い参照が必要です。その参照はメソッドを通じてスコープ内にとどまり、おそらくメソッドが戻るまで解放されません。

これは実際には、コード内の実際のバグを隠している単なる偶然です。問題は、[self.basicInfoContainerView removeFromSuperview]そのビューへの明示的な強い参照がもうないため、basicInfoContainerView が生き残るとは期待できないということです。

もちろん、これを修正する方法は、そのビューへの明示的な強い参照を作成することです。次に、コンパイラに対して意図を明確にしました。コードが最適化されているかどうかに関係なく、必要な結果が得られるはずです。

UIView *containerView = self.basicInfoContainerView
// this local variable is that explicit strong reference you need

[containerView removeFromSuperview];
[self.infoTextView addSubview:containerView];

// the compiler can/will release this view when the local variable
// 'containerView' goes out of scope

それが役立つことを願っています。

于 2013-01-16T23:41:26.703 に答える