I am writing a document-based application for macOS. I am trying to write a feature that changes the active document in the current window (in order to be able to cycle through the next/previous documents in a folder, the way one can do with image-browser apps).
What command should I be calling to open a different document in the current window? The documentation suggests that openDocument might do this, but when I run
documentController.openDocument(nextFile!)
then I just get an NSOpenPanel which opens a new document in a separate window. How can I open a different document in the current window - with a URL I specify in coding, rather than through an OpenPanel?
You can't open a document in the window of another document. Instead of
NSDocumentController -> document -> window
do it the other way around
app delegate -> window/view -> document.
The window is owned by the app delegate or a controller and the view controller of the window owns the document. The document is created with
convenience init(contentsOf url: URL, ofType typeName: String) throws
Edit:
The documentation of addWindowController(_:) of NSDocument suggests that it's possible to replace the document of a window controller:
You cannot attach a window controller to more than one document at a time. The default implementation of this method removes the passed-in window controller from the document to which it is attached, if it is already attached to one, then sends it a document message with self as the argument. It also ignores redundant invocations.
and yes, it does work in my test app:
let prevDocument = windowController.document
let newDocument = Document(contentsOf: newURL, ofType: myDocumentType) // add do-catch
NSDocumentController.shared.addDocument(newDocument);
newDocument.addWindowController(windowController)
prevDocument.close()
Related
Rather than implementing my own document rename method, I would like to use the document browser default view that can be reached by clicking the title of a file in a document browser. To do this I believe that one must call the rename method referenced here. However, this method is for NSDocument and does not work on the iPhone. Is there a similar method for UIDocument or another way to do this altogether?
Like Safari app, in a macOS Swift project I would like to let users to open more than a window and possibly use tabbed browsing to switch from a window to another. The app starts with a blank window and don't need to save or open documents.
A Document Based application seems perfect to me for handle more than a window but I don't want users have to handle documents. How can I disable or hide, if possible, the Open and Save document features?
Edit: if possible, I would like to disable this popup also:
It is very simple - just remove (delete) the Open, Open Recent..., Save, Save as... menu items from the menu XIB. If you don't want a title bar, simply untick the "Title" checkbox for the window in the XIB, though that makes the window difficult to move.
If you have a title bar, to override "Untitled", you could
override var displayName: String! {
get {
return "Anything you like, even \"\""
}
set {
}
}
however that would still allow access to the save as menu through the chevron. To suppress that, you need an NSWindowDelegate Docs
window(_:shouldPopUpDocumentPathMenu:)
Asks the delegate whether the window displays the title pop-up menu in response to a Command-click or Control-click on its title.
Just add autosavesInPlace at true
I've got an OSX document-based app, written in Swift and would like to submit some data from my preferences window controller into my managedObjectContext.
Because the preferences window doesn't seem to be invoked through the NSPersistentDocument, but direct from the appDelegate, what's the best way to get hold of the managedObjectContext for that controller?
Doing most of this using storyboards and bindings so far.
Am I right in thinking that if I instantiate a core-data stack in the application delegate, that negates the one supplied through the NSPersistentDocument (which would be defeating the purpose of the thing)?
What sort of data is this? Are these some sort of settings that are specific to the current document? I am curious only because there may be different solutions here depending on the particulars of what you want to accomplish.
Edit: Usually preferences should be stored using NSUserDefaults, but assuming you do have a specific need to store this data in your persistent document, you should be able to use NSDocumentController to get a list of your persistent documents:
let documents = NSDocumentController.sharedDocumentController().documents
Or get just the current document. Either way you can get the managed object context from there:
if let document = NSDocumentController.sharedDocumentController().currentDocument as? NSPersistentDocument {
if let context = document.managedObjectContext {
// do whatever is needed with the context
}
}
I have a file dialogue opening from the menu where a user can select a file. The FileDialog is called from the menu command's handler class in execute().
Based on the file the user selected, I would like to update a view, for which (I believe) I'd need the same Composite element that's passed to the view in createPartControl().
Is it possible to get access to it from the command handler, or would it be better to trigger the view updating via something like ISourceProviderListener or PropertyChangeListener?
Thank you.
Yes, it's possible:
IViewPart part = HandlerUtil.getActiveWorkbenchWindow(executionEvent).getActivePage()
.findView(viewId);
It would be better to first update the data that your view is displaying (the model in MVC) and the change in data should trigger view refresh. It's hard to say which listener is better without knowing all the details.
Which actions are fired when user uses default NSOpenPanel from Main Menu? How to get the selection from it without creating NSOpenPanel in the code?
A.
Which actions are fired when user uses default NSOpenPanel from Main Menu?
There is no NSOpenPanel in the main menu. There is a menu item "Open…"
The automatism you might "feel" is implemented project dependently. But it is not there automatically. I think that some points has to be clearified:
a. Open Menu Item
The menu item "Open…" sends and only sends the action message openDocument: to the first responder. "Open…" does not open a panel, window dialog or $whatever.
Please get some information about first responders and the responder chain. It is a pity, that even the responder chain is one of the core concept of Cocoa, it is very unknown.
b. Open Panel
If you choosed to have a document based application, when you created the project, some additions are made to your project. In particular,
An instance of NSDocumentController is instantiated automatically.
This instance becomes a part of the responder chain.
Since NSDocumentController implements -openDocument:, it will catch the action message and
run an open panel
creates an instance of NSDocument. (More precise: of the subclass you selected as the document class.)
B.
How to get the selection from it without creating NSOpenPanel in the code?
Create a document-based app and let Cocoa do what it has to do. The base implementation of Cocoa matches 99 % of the cases and can be customized highly.
Do not create a document-based app: Handle the action message yourself, open a open panel yourself, after finishing that, create the instance of a document class and so on.