我正在开发我的第一个基于Mac文档的应用程序。
我已经子类NSDocument,重新实现方法,如
- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
- (void)makeWindowControllers;主窗口控制器是NSWindowsController的子类,包含两个NSViewController子类。
我面临的问题是,我需要从这些视图控制器访问当前文档。我所做的就是打电话
MyDocument *myDocument = [[NSDocumentController sharedController] currentDocument];首先,在启动应用程序之后,就会创建一个新文档。然后,创建主窗口及其视图控制器,但上面的方法返回零。下面是我得到的日志(使用NSLog):
Just created this new document: <MyDocument: 0x10040ff10>
I'm in a view controller and current document is (null)之后,创建一个新文档并调用此方法将生成一个非零指针,但它不是指向正确的文档,而是指向第一个文档:
Just created this new document: <MyDocument: 0x100437e10>
I'm in a view controller and current document is <MyDocument: 0x10040ff10>注意,在第二个文档创建之后,currentDocument指向第一个文档,而不是第二个文档。
知道我错过了什么或者做错了什么吗?currentDocument何时设置为NSDocumentController
发布于 2012-01-18 23:13:16
从苹果关于NSDocumentController currentDocument的文档中可以看出:
此方法如果在其应用程序未激活时被调用,则返回零。这可以在处理拖放操作时发生,例如,在readSelectionFromPasteboard:的实现中。在这种情况下,从与文档关联的NSView子类发送以下消息:
[[[self window] windowController] document];
这有点模糊,因为它并没有真正限定“不活跃”的含义。它可能是拖放操作是唯一的触发器,但它没有说明这是否是一个应用程序变得不活跃的唯一触发器。
也许苹果推荐的替代方案对你是有用的。
发布于 2021-02-08 09:11:22
这是一个古老的话题,但仍然会让人头痛。应用程序的每个窗口控制器必须设置它的document属性,并且它的canBecomeKey getter必须返回true,这样应用程序就知道它必须根据前面的窗口设置当前的文档。
这可能是烦人的管理,特别是当一个应用程序只有一种类型的文件和一些辅助窗口(检查器,首选项,..。)。将这些窗口放在最前面,使当前的文档为零,其中包括我不太理解的其他原因。文档在这个主题上没有那么有帮助(这就是堆栈溢出问题的要点)。
就我个人而言,在大多数情况下,我所做的就是通过使AppDelegate成为一个NSWindowDelegate来管理它。
然后我就可以方便的访问当前窗口,医生,数据.
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
static var shared: AppDelegate { return NSApplication.shared.delegate as! AppDelegate }
weak var mainWindow: NSWindow?
var activeDocument: Document? {
mainWindow?.windowController?.document as? Document
}
var activeData: MyDocumentData? {
mainWindow?.representedObject as? MyDocumentData
}
var mainViewController: DocumentViewController? {
mainWindow?.contentViewController as? DocumentViewController
}
}
extension AppDelegate: NSWindowDelegate {
func windowDidBecomeKey(_ notification: Notification) {
let window = notification.object as? NSWindow
if window != mainWindow {
mainWindow = window
}
}
func windowWillClose(_ notification: Notification) {
let window = notification.object as? NSWindow
if window == mainWindow {
mainWindow = nil
}
}
}在文档类中创建窗口控制器时设置委托。
override func makeWindowControllers() {
let storyboard = NSStoryboard(name: NSStoryboard.Name("Document"), bundle: nil)
let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController
self.addWindowController(windowController)
windowController.contentViewController?.representedObject = self.myDocumentData
windowController.window?.delegate = AppDelegate.shared
}这是迄今为止我发现的最简单的方法,可以在任何时候设置一个连贯的当前文档。
发布于 2012-01-26 02:39:20
有什么原因不能从您的-[self document]子类(或者您的NSViewController子类中的-[[self window] document] )调用-[[self window] document]?这通常是在Cocoa中基于文档的应用程序中实现的。
基本上,当创建NSDocument (子类)时,它会创建所有的NSWindowControllers并将它们附加到文档中。
更重要的是,如果打开了2个文档,并且突然需要绘制这两个文档的内容,[[NSDocumentController sharedController] currentDocument]将不会返回正确的信息。相反,NSWindowController应该控制信息流到其窗口中的视图,以便您可以同时管理前景和背景更改(例如,如果需要同时刷新应用程序中所有窗口的后台存储库,则可能会发生这种情况)。
https://stackoverflow.com/questions/8912314
复制相似问题