2

NSURLドラッグアンドドロップされたファイル( s)を受け入れるビューベースのNSTableViewを使用してサンドボックス化されたARCアプリを作成しています。私は次のNSTableViewDelegate方法でいくつかの重大な奇妙に遭遇しました:

- (NSView *)tableView:(NSTableView *)tv
   viewForTableColumn:(NSTableColumn *)tc
                  row:(NSInteger)row
{
    // `files' is an NSMutableArray* ivar containing NSURLs
    // that have been dropped into this table
    NSURL *url = [files objectAtIndex:row];
    NSString *fileName = [url lastPathComponent];
    NSImage *icon = [self iconForURL:url];

    NSTableCellView *view = [tv makeViewWithIdentifier:[tc identifier] owner:self];
    [[view textField] setStringValue:fileName];
    [[view imageView] setImage:icon];

    return view;
}

1つのファイルをテーブルビューにドラッグすると、正しく表示されます。2番目のファイルをドラッグすると、次のエラーが発生します。

***ドラッグセッション中に例外'NSRangeException'(理由'***-[__ NSArrayM insertObject:atIndex:]:インデックス1が空の配列の境界を超えています')が発生したため、ドラッグをキャンセルしました

デバッガーをステップスルーするfilesと、を呼び出した後、「空になる」(実際には新しいオブジェクトインスタンスになる)ことがわかりましたmakeViewWithIdentifier:owner:。これは私が理解していないARCの一部の側面だと思いますが、オブジェクトはそれ自体のivar(デフォルト)を強く参照しているように見えます。どうすればそれをリリースして、私の下から再作成できますか?

私はこれを回避するために2つのハックを考え出しました:

  1. テーブルセルビューの所有者としてivarを渡します(将来のリリースで強力な参照を保持し続けることを期待します)。また
  2. ivarのオブジェクトを指すローカル変数を作成し、ivarを古いオブジェクトに再割り当てします(これは、その間に置換配列を作成するため、明らかに無駄です)。

ここで何が欠けていますか?これらの回避策は必要ありません。

4

1 に答える 1

2

-makeViewWithIdentifier:owner:を呼び出すと、-awakeFromNibメッセージが所有者に送信されます。これは文書化されていますが、ヘッダーファイルにのみ記載されています(編集:メインの文書はこれを参照するように更新されています)。

あなたのファイル配列は単に-awakeFromNibで再初期化されていると思います。

与えられたケース(ペン先ではなくビューのプロトタイプをロードしている)の解決策は、単に所有者としてnilを渡すことです。登録されたペン先をロードする他の実装(-registerNib:forIdentifier :を参照)には、デリゲートである(またはされていない)所有者が必要になる可能性があります。したがって、への複数の呼び出しを-awakeFromNib検出してトラップする必要がある場合があります。ペン先の読み込みにフラグを立て、必要な初期化を1回だけ実行するようにプロパティを設定するのは簡単です。

このメソッドのAppleドキュメントは、これを反映するように更新されていることに注意してください。

このメソッドが呼び出されるたびにawakeFromNibが呼び出されることに注意してください。つまり、所有者がすでに起動している場合でも、所有者に対してawakeFromNibも呼び出されます。

于 2013-12-19T12:09:51.737 に答える