如何检查响应链?
我正在使用基于文档的架构在一个窗口内做一些疯狂的多个文档,并且已经完成了 95%。
我有一个两层文档体系结构,其中父文档打开并配置窗口,提供“子”文档列表。当用户选择其中一个子文档时,该文档将使用相同的窗口控制器打开,并在窗口中放置一个 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
文档来看,链似乎应该是这样的:
Current View ->超级视图(重复)->窗口->窗口控制器->文件->文档控制器 ->应用。
我不确定基于文档的架构如何设置响应者链(即如何将 NSDocument
和 NSDocumentController
放入链中),所以我想调试它,但我不知道该去哪里寻找。如何在任何给定时间访问响应者链?
I'm doing some crazy multiple documents inside a single window stuff with the document-based architecture and I'm 95% done.
I have this two-tier document architecture, where a parent document opens and configures the window, providing a list of "child" documents. When the user selects one of the children, that document is opened with the same window controller and it places a NSTextView
in the window. The window controller's document association is changed so that the "edited dot" and the window title track the currently selected document. Think of an Xcode project and what happens when you edit different files in it.
To put the code in pseudo form, a method like this is invoked in the parent document when a child document is opened.
-(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];
}
}
This works, and I know the window controller has the correct document association at any given time since the change dot and title follow whichever document I'm editing.
However, when I hit save, (CMD+S, or File -> Save/Save As) it wants to save the parent document, not the current document (as reported by [[NSDocumentController sharedDocumentController] currentDocument]
and as indicated by the window title and change dot).
From reading the NSResponder
documentation, it seems like the chain should be this:
Current View -> Superview (repeat) -> Window -> WindowController -> Document -> DocumentController -> Application.
I'm unsure how the document based architecture is setting up the responder chain (i.e. how it's placing NSDocument
and NSDocumentController
into the chain) so I'd like to debug it, but I'm not sure where to look. How do I access the responder chain at any given time?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以使用 nextResponder NSResponder 的方法。对于您的示例,您应该能够从当前视图开始,然后重复打印出在循环中调用它的结果,如下所示:
You can iterate over the responder chain using the nextResponder method of NSResponder. For your example, you should be able to start with the current view, and then repeatedly print out the result of calling it in a loop like this:
这是 Swift 用户的另一个版本:
只需用 self 调用它即可打印出从 self 开始的响应者链。
Here is another version for Swift users:
Simply call it with self to print out the responder chain starting from self.
我将通过使用在调试时感觉更“可用”的类方法来改进响应程序类别答案(您不需要在特定视图或其他内容中中断)。
代码适用于 Cocoa,但应该可以轻松移植到 UIKit。
I'll improve a bit on the Responder category answer, by using a class method which feels more "useable" when debugging (you don't need to break in a specific view or whatever).
Code is for Cocoa but should be easily portable to UIKit.
您还可以使用适当的方法向 UIResponder 类添加一个类别,该方法可由 UIResponder 的任何子类使用。
您可以在代码中的某处使用此方法,如下例所示:
You can also add a category to class UIResponder with appropriate method that is possible to be used by any subclass of UIResponder.
Than you can use this method somewhere in code as the example below:
迅速:
Swift:
这是最简单的一个
Here is the simplest one