11

注: これは、長い間修正されてきた一部の XCode ベータ バージョンのバグによるものです。ARC に問題がある場合、この質問と回答は役に立たないでしょう。


プロジェクトを手動参照カウントから ARC に移行していますが、問題に遭遇しました:保持プロパティのカスタム セッターが実際に保持されていることを確認するにはどうすればよいですか?

ではmyClass.h、プロパティを宣言しました: @property (retain) NSDate *date__strongivarを手動で設定するか、自動生成するかは問題ではありません。

実装では、もちろん@synthesize date、カスタム セッターを実装しました (またはデモ Xcode プロジェクトをダウンロードするだけです)。

- (void)setDate:(NSDate *)newDate
{
  if (allowedToSetNewDate)
  {
    date = newDate;
  }
}

これは日付を保持していないようで、後でmessage sent to deallocated instanceアクセスしようとしたときに、newName が元の場所で (自動) 解放されたときに私に知らせますmyClass.date(Zombie が有効になっている場合、それ以外の場合は静かにクラッシュします)。

セッターを使用するように変更するとdate = [newDate copy]、エラーを回避できますが、実際には必要ありません。カスタム セッターの削除も機能しますが、明らかに望ましくありません。

ここで何が欠けていますか?保持プロパティのカスタム セッターが実際に ARC 環境で保持されるようにするにはどうすればよいですか? これは非常に基本的で一般的なタスクのように思われるため、非常に明白なことを見落としていると思います。

(注: ARC は LLVM の一部として公開されているため、これは Apple NDA の条件には該当しません)

編集:問題をデモする小さな Xcode プロジェクトを作成し、github にアップロードしました。気軽にダウンロードして遊んでみてください。私は機知に富んでいます (確かに、今日の機知は最高ではありませんが)。

編集: このサンプル プロジェクトでは、この問題は解決されています (受け入れられた回答を参照)。残念ながら、私が共有する自由がないより大きなプロジェクトでは、問題は解決しません。回避策として、合成されたセッターを使用して重複したstrongプロパティを追加しました (ivar は機能しません)。新しいカスタム セッターは次のようになります。

- (void)setDate:(NSDate *)newDate
{
  if (allowedToSetNewDate)
  {
    self.date_arcretain = newDate; //this property is only there as a workaround. ARC properly retains it, but only if the setter is synthesized
    date = newDate;
  }
}
4

2 に答える 2

12

これは私にはバグのように見えます。あなたのコードは問題ないはずです。まだ行っていない場合は、http://bugreport.apple.com でバグを報告し、サンプル プロジェクトを添付してください。

編集:サンプルプロジェクトをさらに調べると、これはバグではありません。

サンプル プロジェクトのオーバーリリース オブジェクトはインスタンスではありません。NSDateサンプル プロジェクト内の呼び出しを完全にコメント アウトすることができtc.date = nowますが、それでも同じクラッシュが発生します。実際、NSDate のものを完全に取り除くことができます。過剰解放されたオブジェクトは、実際にはTestVCオブジェクトそのものです。

これが何が起こっているかです。

iOS 4.0 ではUIWindow、プロパティを取得しましたrootViewController。以前[self.window addSubview:myRootcontroller.view]はアプリの起動時に呼び出すだけでしたが、この変更により、ウィンドウが実際にルート ビュー コントローラーへの参照を持つようになりました。これは、ローテーション通知などを渡すために重要です。以前は、最初のサブビューが追加されたときに (まだ設定されていない場合)、UIWindow が rootViewController を自動的に設定しようとすると考えていましたが、サンプル プロジェクトでは明らかに起こっていません。これは、ビューの作成方法が原因であるか、iOS 5.0 の変更が原因である可能性があります。いずれにせよ、それは文書化された動作ではなかったので、それが起こっていることに依存することはできません.

ほとんどの場合、アプリ デリゲートには、ルート ビュー コントローラーを指す ivar があります。厳密には必須ではありませんが、通常は発生します。ただし、提示したサンプル プロジェクトでは、ビュー コントローラーはアプリ デリゲートによって所有されていません。また、ウィンドウのルート ビュー コントローラーとしても設定しませんでした。その結果、-application:didFinishLaunchingWithOptions:メソッドの最後には、View Controller への強い参照が何も残っていません。アプリのデリゲートはそれを保持しておらず、ウィンドウ自体も保持していません。そのため、ARC はそれをローカル変数 (つまり) として扱い、メソッドの最後で解放します。

もちろん、UIButtonコントローラーを対象としたアクション メソッドがまだあるという事実は変わりません。ただし、ドキュメントに記載されているように-addTarget:action:forControlEvents:、ターゲットは保持されません。そのUIButtonため、View Controller へのダングリング参照があり、誰も強い参照を持っていないため、割り当てが解除されました。したがって、クラッシュ。

これを修正するには、アプリのデリゲートで次の行を変更します。

[self.window addSubview:tc.view];

これに:

self.window.rootViewController = tc;

その 1 つの変更で、すべてが正常に機能するようになりました。

編集:また、「ARC移行のコードを事前にチェックする」設定がオンになっていないことを確認してください.

于 2011-08-14T15:32:18.257 に答える
2

あなたのプロジェクトで私のMacで修正しました。エラーは、日付プロパティではなく、AppDelegate にあります。View Controller を AppDelegate で保持可能なプロパティにします。現在、View Controller はすべてのプロパティを含めて自動解放されています。

于 2011-08-14T16:02:31.920 に答える