NSDocument for relational data / todo list? - macos

I want to create an OS X app where users can edit items from something similar to a todo list - each item has text, status (done/todo), creation date and some other data. The items of the todo list have also relationship with other entities.
I created an iOS app for this which uses a core data data model... Now I want to make an OS X app and sync.
I'm new to OS X development and just stumbled upon NSDocument, and wondered if this could be usable. I just want that the user sees the list similar to an excel table and can edit it. I found some examples to store only a string e.g. https://developer.apple.com/library/mac/documentation/DataManagement/Conceptual/DocBasedAppProgrammingGuideForOSX/ManagingLifecycle/ManagingLifecycle.html or this tutorial http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1
There's also NSPersistentDocument to work with core data, which I think is what I would have to try out.
But generally speaking, does it have any benefit to use NSDocument for my todo list? One could be the undo functionality but I'm not sure if this is applicable. Any advices?
I'm also not sure if I have to use one document for each todo or rather load them all in one document, and if this works correctly with table view... Maybe in a todo app I will never get hundreds of entries, but principally I could. Would I be able to paginate, etc.?
Thanks!
Edit: I just read Document-based application, or not? specially "The key question is one of independence. If all of the objects in your application's model are related then there's no need to manage independent documents." Not sure how to apply this to my model... It's relational. Some 1:1 and 1:n relationships. Does this mean that all my objects are related? Or can I still treat them as "independent" documents...?

If the app has just one todo list, there's no benefit to using NSDocument. Use Core Data, and you'll get undo support without having to use NSDocument.
NSDocument would help if your app lets people create multiple todo lists and save each list in its own file. NSDocument is designed for apps like word processors and spreadsheets where people can create multiple documents and have multiple documents open at once. If you were to use NSDocument for this app, each todo list would be its own document.
UPDATE
The main benefits of NSDocument involve the File menu. When you use NSDocument, choosing File > New creates a new document. Choosing File > Open opens an Open File dialog for you to load a document from disk. Choosing File > Save when you save a new document opens a Save File dialog for you to save the document as a file on disk.
When determining whether or not to use NSDocument, ask yourself the following questions: Do you want the user to create a new todo list by choosing File > New? Do you want the user to save the todo list as a separate file by choosing File > Save? Do you want the user to open todo lists by choosing File > Open? If the answer to these questions is YES, NSDocument will help you. If the answer to these questions is NO, NSDocument won't help you. Also, NSDocument will not help you when dealing with the "other documents" that reference the individual todos in the lists.
To answer your question about iOS syncing, are you using UIManagedDocument in your iOS app? If so, you can use NSPersistentDocument in your Mac app and share the same Core Data model. If not, you won't be able to use NSPersistentDocument. You'll have to use NSManagedObject in your Mac app to use the same Core Data model in both the iOS and Mac apps. It's possible to use NSDocument and Core Data together without using NSPersistentDocument, but I don't know how to use them together. But if you are not using UIManagedDocument in your iOS app, that is a sign that you should not use NSDocument in your Mac app.

Related

Cocoa how to handle multiple views?

I'm have done some development on iOS using Storyboards. Now I'm building on app for Mac OS X and it seems that an equivalent for Storyboards does not exists.
For instance, I'm need to build some kind of wizard, which contains four different windows or views (step 1 to 4).
Currently I've created one Window xib (the standard MainMenu.xib), containing a window with the first view, and three other custom views. Using this approach, I can create outlets and actions, making me able to change the contentView of my window, e.g. when clicking an button. This seems as a fair solution, and my views are all grouped cleanly inside a single xib. But this also cause that the logic for all the view should be handled by the same File's Owner, right? For instance saving the settings on each step and controlling the interaction between the different views.
How is the preferred way to handle a situation like this? Should I instead create four different windows, and maybe in four different xib-files? If you know an sample project somewhere from the internet showing how to handle multiple windows, please give me a hint.
You can make use of the NSViewController class for this purpose. Each view controller will be responsible of loading a xib associated with it and all logic associated with the views can go inside the controllers (Same as in iOS). The MainMenu.xib can now load appropriate views after initialising the required view controllers.
Here is a sample app for your reference.
https://developer.apple.com/library/mac/samplecode/ViewController/Introduction/Intro.html
In xcode, go to File->New->New File
Add an objective C class and set it to subclass of "NSViewController".
This will itself create yourController.h, yourController.m and yourController.xib.
Now you can keep your view and its controller class seperate.

Steps to convert a new xcode cocoa project using 1 controller per nib

I want to start off my new xcode project using 1 nib per controller. By default it seems xcode creates:
1. delegate .h/.m
2. MainMenu.xib
And looking at the targets for the project, I see that the 'main nib file base name' is set to MainMenu, the principal class is NSApplication.
Since cocoa is MVC based, how are things MVC based on the default template?
How can I wire things together with a 'MainWindowController' instead of this default setup? If someone can explain the steps to me that would be much appreciated.
You don't want to subvert or change the default setup, just to understand it and work within it. MVC is a description of responsibility rather than some hard requirement about naming.
The delegate .h/.m is the app delegate by name, but its responsibility is to be the app controller. It gets everything setup when the app starts and deals with application level events. It shouldn't do anything that isn't related to application level management.
The MainMenu.xib is just a container / archive of the first Views and Controllers that are to be created when the application opens.
There is no Model in the template really as all it does is display the main window with a static string on it...
Your goal of using 1 nib per controller is fine, but you should be a little flexible with the naming at first. Because the MainMenu.xib contains the main window it should also contain your MainWindowController. This is perfect from an MVC point of view because you are separating the responsibility.
Then, your future Controllers and Views (in their XIBs) can have matching names to keep everything clear. And you can created your Model separately.

How to add a custom object to Xcode?

I want to create an object and use it on my project. I able to do it, but under the objects panel of xib file there is a pop up list that shows these values:
Cocoa touch [Controls, Data Views, and ...]
Custom objects
The Custom objects list is empty! Is any way to add my objects to this list? What is this list exactly?
This list is indeed meant to save custom object templates. You could create those custom objects and then pull them into the list for later reuse.
However, it doesn't seem to work in the current stable version (4.5.2) of Xcode.
You should check if it works in the latest developer preview. If it doesn't you should probably file a bug.

What do you bind NSArrayController's Managed Object Context to in Xcode 4?

I am trying to build an document-based application for beer reviewing that allows you to enter your notes. I have built the model in Core Data and the view in Interface Builder. Following some Xcode 3-based tutorials, I am told to connect the new NSArrayController to the managedObjectContext of File's Owner. If I try and do this in Xcode 4, a circled exclamation point comes up next to "Model Key Path" in the inspector for the NSArrayController.
I can actually load the .xib file in Interface Builder in Xcode 3, make that connection, and then build it in Xcode 4 and it runs, but every field raises a validation error.
The model has an entity named Scoresheet, which has a property named date, which is an NSDate. But if I link it to the value of an NSDatePicker and try to save it to disk, it says I have "multiple validation errors." How can that be? They are both NSDates, right? Actually, I have the same problem with bindings to everything; none of my UI objects will work with my model.
The only thing I can figure is that there is something going wrong in the connection between the File's Owner and the NSArrayController.
I haven't written any code at this point, because I'm of the understanding I shouldn't have to just to link UI fields and core data. Is it different because I am using a document-based application? (I can't get it to work in a single window app, either.)
An answer of "don't use Core Data" isn't going to be productive; I know I can just fall back on a regular data object. I would like to figure this out in the context of Core Data if possible.
TIA!
(Update: this question seems to be vexing a lot of people. I have consulted the Zarra book on Core Data, the Hillegas book on Cocoa Programming, and two O'Reilly books. They all seem to be based on Xcode 3.)
NSPersistentDocument has it's own managed object context, and you should bind the NSArrayController in your document's xib file to that managed object context.
For example, if your document class is called MyDocument, then Xcode will automatically generate a MyDocument.h / .m / .xib for you. In the .xib, the File's Owner is an instance of your MyDocument class, and you can bind the NSArrayController to this, with the binding File's Owner -> managedObjectContext.
I am running into the same problem (the CarLot example in Chapter 11 of Hillegass, right?)
The following blog entry is from a developer who wrote and maintains an extension for use with NSManagedObjects and considers this a bug in XCode 4 and has filed a report in rdar : http://danieltull.co.uk/blog/2011/04/20/xcode-4-and-creating-nsmanagedobject-subclasses/
I have a machine with XCode 3 on it, I will eventually give up beating on this in 4, create the project in XCode 3 and import it into XCode 4.
Edited to add: Adding the element in XCode 3 and linking the outlet, and then importing the project into XCode 4 works fine, it does seem that this is a bug in XCode 4. I do not get validation problems from XCode 4 doing this.

Cocoa document-based application with multiple document types

I want to build a document-based app in Cocoa but so that it can create and handle different types of documents. Think Word, Excel, Powerpoint all in one application, only much simpler. But every window will be different based on the type of document.
For storage I will use CoreData. I think of adding a field that specifies the type of document since they should all have the same file ending.
So without creating several independent apps what would be the best way to go about it? How do I create this in Interface Builder? How do I code this up?
I don't need detailed source code or anything, just the general idea of how to do this, I will figure the rest out.
Thanks in advance!
This is something the Cocoa Document system is explicitly designed to do. Apple provides documentation, but here are the highlights.
Each kind of document is a subclass of NSDocument. If you're using Core Data, base your class on NSPersistentDocument instead. (Apple has a basic tutorial on how to use Core Data in a document-based application)
You tell Cocoa about the kinds of documents your application can open, and which document class to use, with the Info.plist.
Each NSDocument subclass has one or more NSWindowController objects associated with it, each of which represents a single window. If you'll only have a single window, you don't have to subclass NSWindowController. You can put your UI logic in your document subclass. However, for cleaner code, I'd strongly recommend subclassing NSWindowController.
NSWindowController (and NSDocument if you decide not to subclass NSWindowController) can load a window from a NIB you build in Interface Builder. In fact, this is the recommended approach for creating your document windows.
Hopefully this gives you a general idea of how to approach this in Cocoa.
You would start by creating a NIB for each of your document types; and an NSDocument subclass for each (use an existing document-based-app-example-NIB for the setup here). You would then set theses classes to handle your various document types in the property list of the application; insofar as I remember, there are some useful tools for this hidden somewhere in XCode.
Once that is up an running, most of the details should be handled automagically; but you might still have to fudge the File-menu about a bit, and I seem to remember there being some trouble with setting the default document type and whatnot.
On the whole, tho', it's not a lot more complex than creating an app for a single kind of documents.
PS: Do take care to ensure that you really need different filetypes; sometimes it might be more appropriate having several different views of the same file. Just a thought. :)

Resources