22

ドキュメントベースのアーキテクチャを使用して、単一のウィンドウ内でクレイジーな複数のドキュメントを処理していますが、95% 完了しています。

親ドキュメントを開いてウィンドウを構成し、「子」ドキュメントのリストを提供する、この 2 層ドキュメント アーキテクチャがあります。ユーザーが子の 1 つを選択すると、そのドキュメントが同じウィンドウ コントローラーで開かれNSTextView、ウィンドウに が配置されます。ウィンドウ コントローラのドキュメントの関連付けが変更され、「編集されたドット」とウィンドウ タイトルが現在選択されているドキュメントを追跡するようになります。Xcode プロジェクトと、そのプロジェクト内のさまざまなファイルを編集するとどうなるかを考えてみてください。

コードを疑似形式にするために、このようなメソッドは、子ドキュメントが開かれたときに親ドキュメントで呼び出されます。

-(void)openChildDocumentWithURL:(NSURL *)documentURL {
  // Don't open the same document multiple times
  NSDocument *childDocument = [documentMapTable objectForKey:documentURL];
  if (childDocument == nil) {
    childDocument = [[[MyDocument alloc] init] autorelease];
    // Use the same window controller
    // (not as bad as it looks, AppKit swaps the window's document association for us)
    [childDocument addWindowController:myWindowController];
    [childDocument readFromURL:documentURL ofType:@"Whatever" error:NULL];

    // Cache the document
    [documentMapTable setObject:childDocument forKey:documentURL];
  }

  // Make sure the window controller gets the document-association swapped if the doc came from our cache
  [myWindowController setDocument:childDocument];

  // Swap the text views in
  NSTextView *currentTextView = myCurrentTextView;
  NSTextView *newTextView = [childDocument textView];
  [newTextView setFrame:[currentTextView frame]]; // Don't flicker      

  [splitView replaceSubview:currentTextView with:newTextView];

  if (currentTextView != newTextView) {
    [currentTextView release];
    currentTextView = [newTextView retain];
  }
}

これは機能し、編集中のドキュメントに変更ドットとタイトルが続くため、ウィンドウコントローラーはいつでも正しいドキュメントの関連付けを持っていることがわかります。

ただし、保存を押すと(CMD + S、またはファイル->保存/名前を付けて保存)、現在のドキュメントではなく親ドキュメントを保存します([[NSDocumentController sharedDocumentController] currentDocument]ウィンドウタイトルと変更ドットで報告および示されます)。

ドキュメントを読むNSResponderと、チェーンは次のようになります。

現在のビュー -> スーパービュー (繰り返し) -> ウィンドウ -> WindowController -> ドキュメント -> DocumentController -> アプリケーション。

ドキュメント ベースのアーキテクチャがレスポンダ チェーンをどのように設定しているか (つまり、どのようにチェーンに配置NSDocumentNSDocumentControllerているか) がわからないので、デバッグしたいと思いますが、どこを見ればよいかわかりません。いつでもレスポンダー チェーンにアクセスするにはどうすればよいですか?

4

6 に答える 6

44

NSResponder のnextResponderメソッドを使用して、レスポンダー チェーンを反復処理できます。あなたの例では、現在のビューから始めて、次のようなループで呼び出した結果を繰り返し出力できるはずです。

NSResponder *responder = currentView;
while ((responder = [responder nextResponder])) {
     NSLog(@"%@", responder);
}
于 2010-11-22T03:33:33.640 に答える
3

UIResponder の任意のサブクラスで使用できる適切なメソッドを使用して、クラス UIResponder にカテゴリを追加することもできます。

@interface UIResponder (Inspect)

- (void)inspectResponderChain; // show responder chain including self

@end

@implementation UIResponder (Inspect)

- (void)inspectResponderChain  
{
    UIResponder *x = self;
    do {
        NSLog(@"%@", x);
    }while ((x = [x nextResponder]));
}
@end

以下の例のように、コードのどこかでこのメソッドを使用できます。

- (void)viewDidLoad {
    ...
    UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    [self.view addSubview:myView];
    [myView inspectResponderChain]; // UIView is a subclass of UIResponder
    ...
}
于 2015-10-11T09:11:38.767 に答える