4

データ入力に複数のモーダル シートを使用するアプリがあります。モーダル シートを開く方法は正常に機能し、今でも正常に機能しますが、廃止されており、Xcode の将来のリリースではすぐに機能しなくなるのではないかと心配しています。 ここで、アップルはモーダルシートの使い方を指摘し

    - (void)showCustomSheet: (NSWindow *)window

// User has asked to see the custom display. Display it.
{
    if (!myCustomSheet)
//Check the myCustomSheet instance variable to make sure the custom sheet does not already exist.
        [NSBundle loadNibNamed: @"MyCustomSheet" owner: self];

    [NSApp beginSheet: myCustomSheet
            modalForWindow: window
            modalDelegate: self
            didEndSelector: @selector(didEndSheet:returnCode:contextInfo:)
            contextInfo: nil];

    // Sheet is up here.
    // Return processing to the event loop
}

しかし、Xcode 5.1 のリリースにより、loadNibNamed メソッドが非推奨になり、トップレベル オブジェクトを参照する同様の関数を使用する必要があることが明らかになりました。

私が抱えている問題は、これを変更することです:

[NSBundle loadNibNamed:@"OrderDetailsWindow" owner:self];

これに。

NSArray *array;
[[NSBundle mainBundle]loadNibNamed:@"OrderDetailsWindow" owner:self topLevelObjects:&array]; 

このメソッド呼び出しは、実際にはモーダル シートを開きます。ただし、モーダル シートを開くメソッドの最後で、Xcode がこのエラーでハングアップします。

0x7fff8c33b097:  andl   24(%r11), %r10d    Thread1: EXC_BAD_ACCESS (code:EXC_I386_GPFLT)

これが何を言っているのかわかりません。デバッグ領域に情報はありません。これは、topLevelObjects 配列が適切に解放されていないことに関係しているのでしょうか? この作業をもう少しスムーズにする方法について何か考えはありますか? Apple の時代遅れのライブラリに頭がおかしくなりそうです!

4

2 に答える 2

4

はい、Apple のドキュメントはめちゃくちゃです。「シート プログラミング トピックス」ドキュメントは 2009 年以降更新されていません。

変更後の完全なコードは表示されませんが、問題は NIB のオブジェクトのメモリ管理にあると思います。

新しいドキュメントからloadNibNamed:owner:topLevelObjects:

従来の方法とは異なり、オブジェクトは標準のココア メモリ管理規則に従います。IBOutlets を使用するか、配列への参照を保持して nib の内容が割り当て解除されないようにすることで、それらへの強い参照を保持する必要があります。

最上位オブジェクトへのアウトレットは、所有権を示し、割り当て解除を防ぐための強力な参照である必要があります。

メソッド内にトップレベルのオブジェクトを保持する NSArray があります。実行がこのメソッドを離れると、NSArray は逆参照されて解放され、他の場所で強く参照されていない場合はすべての最上位オブジェクトも解放されます。

NIB の最上位オブジェクトを Window Controller のアウトレットに接続するか、NSArray を Window Controller インスタンスのメンバー変数として保持する必要があるため、シート表示メソッドが終了すると解放されません。また、myCustomSheet が適切に宣言され、シートの NIB から接続されていることを確認してください。

また、[NSApp beginSheet:]同様に廃止され、NSWindow のインスタンスで beginSheet を呼び出すようになりました。

于 2013-10-31T15:25:53.527 に答える
0

私は常にNSWindowControllerシートのカスタム デリゲートを持つサブクラスを使用します。

シートを表示したいウィンドウから:

_myModalController = [[MyModalController alloc] init];
_myModalController.delegate = self;
[_myModalController beginSheet:self.window];

次に、モーダル ウィンドウ コントローラー内に、次のものがあります。

- (id)init {
    self = [super initWithWindowNibName:@"MyModalWindow" owner:self];
    return self;
}

- (void)beginSheet:(NSWindow *)mainWindow {
    [NSApp beginSheet:[self window]
       modalForWindow:mainWindow
        modalDelegate:self
       didEndSelector:@selector(_didEndSheet:returnCode:contextInfo:)
          contextInfo:nil];
}

- (void)endSheet:(NSWindow *)mainWindow {
    [NSApp endSheet:[self window]];
    [[self window] orderOut:mainWindow];
}

loadNibNamed:これにより、非推奨になるという問題全体が回避されるようです。

于 2013-10-31T15:38:08.447 に答える