Switching between NSViewControllers - xcode

I'm developing a Mac Application. The application has a common source view on the left and a detail view on the right which is the main part of the whole window.
It's like a Master-Detail relationship, but each element in the source view require another detail view. In fact, I have designed a specific NSViewController for each element in the source view.
If I'm switching between these NSViewControllers, that means If I select another element in the source view, I remove the current view and add the view of the newly selected NSViewController. Everytime I change the NSViewController, its state will be lost. When the user comes back to that NSViewController, he has to start over.
My question now is: How can I save the state of the NSViewController, so that I can switch between these without losing its states and can continue where I have left?

Two considerations about your problem:
Keep model data in model classes. This means that you can always recreate a view controller and set its represented object provided the model classes have kept the changes made via the view controller. When you need to instantiate a view controller, set its represented object to (a representation of) a model class.
When removing a view from its superview, you do not necessarily need to release its corresponding view controller. Instead, you can keep strong references to all view controllers in your window controller/application delegate, so no state is actually lost.

Use NSArchiver. Implement archiving/unarchiving in your dealloc/init methods and store each view controller's state in a file named after the class (if you have one item per view controller policy). Otherwise think of some simple naming convention and use it.

Related

Laravel multiple model bound forms in a parent view

The overall concept that I'm attempting to do is create admin panel that has multiple "forms" on a single blade view. Each "form" is a blade.php file that has a form that is model bound to provide quick access to the model data on load. For example, let's say that I'm running a manufacturing line and there are three models (subviews) that I want to #include() on manufacturing.blade.php.
Parent view (manufacturing.blade.php)
Subview - Start time (start-time.blade.php)
Subview - Throughput (throughput.blade.php)
Subview - Supervisor (supervisor.blade.php)
Each subview has a submit button on it that POSTS to the assigned resource controller. My problem is how do I successfully load manufacturing.blade.php and include form model binding when I never call the index controller on the subviews.
Is what I'm asking even possible?
For what it's worth I figured it out right after I posted the question. The variables required for the model binding inside the subviews were the problem. I was receiving errors about the variables not available, blah.... when I loaded the parent view page. Obviously the variables aren't available when I call the subviews because they were never pulled in from the parent view. In other words I'm trying to access something that isn't there.
Solution:
In the parent view loading controller, perform all the necessary db call to obtain/generate the objects required for the subviews. After the objects are obtained use
View::share('startTime', $startTime);
View::share('throughput', $throughput);
View::share('supervisor', $supervisor);
That method (view::share) allows that variable, 'startTime', etc..., to be shared across all the blade views that reside inside of parent. Just be sure you add the lines right before you return the intended parent view from your controller.

Connect two NSObjectControllers within a multi view OSX Storyboard

I'm using Storyboards for the first time creating a master/detail view for a simple object.
Both view controller items of the split view have their own view & NSObjectControllers. The controller for the table view is a NSArrayController (which shows all instances of the Entity). The controller for the detail view is an NSObjectController, which shows just the selected instance.
When I click an object in the table, I'd like the detail to show up in the detail view. So I believe my goal here is to bind the 'contents' of the detail object controller to the 'selection' of the master array controller. However with storyboards I cannot cross view controller boundaries (can't create the IB 'link'. aka: can't bind cross VC).
Whats the best practice for doing this?
So far all I can think to do is manually set all this up in one of the controllers (either the root controller, window controller or perhaps the master table view controller) - but that seems counterintuitive. That seems to defeat the purpose of being able to lay out this stuff within storyboards in the first place, and my controller of choice would then have to know about the other controller specifically.
I must be missing something!

Best practice for setting a data source and delegate for a UITableView

This question may not have a straight answer, but I am curious as to what others think. I have a UIViewController and inside that I have 2 objects a UIView and and UITableView. Each object as it's own custom class. My question is about the UITableView, what object should be the datasource and the delegate. Right now I have the UIViewController set to those rolls, but is it beset practice to set the object itself to be the data source and the delegate, maybe use the method awakeFromNib to set those 2 sources. Are both ways ok? I would think that setting the data and the delegate to the class that represents the tableview would keep that code apart from the view controller, which I would think would be a good thing.. but maybe not...
Good question actually.
Look at the Controller as an example of the Mediator Pattern from the Gang of Four: it's mediating the relationship between the View and the Model. Most of the web world has gone to using binding of some sort, so you typically see model objects 'bound' directly to the view layer, e.g. a text edit field might have an expression indicating which field in the domain object it is editing, then the framework will provide the services of marshaling and unmarshaling that data.
In Cocoa, you typically don't do that: you bind to properties in the Controller, and those typically are then used to transform the underlying domain class. So for instance, if you make a storyboard and make a form and have a custom controller, now you want to edit the name of some entity, e.g. User, you would CTRL-drag from the edit box over to the source, it would make an outlet, which would then give you control not only of what appears in that box, but the control itself. Then you could add a submit button and CTRL-drag to create a method, for Save, and when that's clicked, you could update the underlying User instance.

Cocoa MVC: interaction between "model controller" and "view controller"

Just started learning Objective-C and Cocoa with the help of BNR's Cocoa Programming for Mac OS X (4th Ed.), and I'm working on a document-based application. I've read through Apple's developer documentation on the document architecture, and have chosen to subclass NSWindowController and override makeWindowControllers on my NSDocument subclass. I have a few reasons for doing this:
to separate model logic (in NSDocument subclass) from view logic (in NSWindowController subclass).
to customize the title of my document windows (Apple's developer documentation says that the proper way to do this without unwanted side effects is to subclass NSWindowController and override windowTitleForDocumentDisplayName:
Apple's documentation seems to strongly suggest subclassing NSWindowController for all but the simplest of applications, and mine is definitely not "simple"
So, my NSDocument subclass is a model controller, and my NSWindowController subclass is a view controller. Further, I understand that most of an application's "work" is done in the controller objects, as the views and models should be as application-agnostic and reusable as possible. Now comes my question: how do these two types of controllers interact to actually do this "work"?
For example, imagine I'm writing a spreadsheet application, and I want to have a menu item (or toolbar button) that brings up a sheet for creating a chart or graph from some of my data. In that sheet, the user will enter various parameters and options for how to create the chart or graph, then click "OK" (or whatever the button is called).
Who should respond to the menu item's action, the document (model controller) or the window controller (view controller)? The task of actually loading and showing the sheet seems decidedly "view-related", so it should go in the window controller, correct? But the controller for the sheet needs a model to display to the user (a Chart object, or maybe ChartInputs); where does that model get created and given to the sheet controller? Should the document respond to the menu item by creating the ChartInputs model object, then pass that to the window controller, which creates the sheet controller, passing it the model object, and shows the sheet? Or should the window controller respond to the menu item, request a new model object (perhaps through some sort of factory provided via dependency injection into the constructor of the window controller), then proceed with creating the sheet controller, passing the model, and showing the sheet?
What about after the user fills out the sheet and clicks "OK"? Where should control be returned to process the user's choices and actually create the chart -- window controller, document, or both? What about logic to validate the user's inputs after they click "OK", but before the sheet is dismissed (in case something is invalid)?
To begin, consider windowless operation of your NSDocument. For example, you might create a utility application which shares your NSDocument class, opening documents for scripting, printing, or other manipulation, but without presenting your primary document window. Imagine your NSDocument class reused for that application – and put the logic you wouldn't want into your window controller. This way, the NSDocument subclass is primarily responsible for activities which affect the document's state.
These are the responsibilities of the model-controller (NSDocument subclass):
Serialization and deserialization
Loading and saving
Manipulating the document's state
Managing and dispatching print views
Monitoring the document for changes by others
Refreshing supporting data sources – sources which affect the document model – and applying changes to the model and document as needed
Managing an activity log related to the document
Owning the undo manager
Exposing the essential model objects to the view controller
Creating window controllers
Facilitating some editing behaviors, such as a change to one property triggering creation or removal of objects
If you're using Core Data, your managed object context, persistent store coordinator, and persistent store are part of the model-controller, not the model. Of course the managed objects themselves are part of the model.
This leaves these responsibilities to the model:
Helper methods for inserting, rearranging, and deleting model objects
Helper methods for accessing specific parts of the model
Data validation
Rendering the model to strings, in various formats
Serializing and deserializing oneself
Facilitating some editing behaviors, such as a change to one property triggering changes to other properties
On the other side, these are the responsibilities of the view-controller:
Manipulating the view to keep it in sync with the model
Manipulating the view to keep it in sync with the document state
Responding to localized actions, such as a button which adds or removes a model object
Presenting auxiliary views and responding to input in those views
Dispatching actions which are affected by selections in the UI, such as the selected rows in a table view
Managing auxiliary controllers used during editing, which are not related to the document itself (such as web-service data)
Serving as a data source for view objects
If you're using Cocoa Bindings, your bindings also part of the view controller.
This design produces a reasonable separation of responsibilities between the view-controller and model-controller. However, they both sit between the view and model. While this produces modularity it doesn't produce decoupling.
Though I did consider windowless operation, I largely arrived at this design pattern empirically – by placing similar code together and separating code that felt out-of-place. I'm curious if others post authoritative sources or references which agree or disagree about how to do this.
To take up your example, I'd suggest this design:
EditorWindowController creates ChartParameters object and gives it a reference to the document's model:
[[ChartParameters alloc] initWithWorkbook:self.document.workbook]
EditorWindowController sets up the new-chart view, which probably has its own NewChartViewController. It passes the ChartParameters and document objects to the NewChartViewController and displays the window.
The ChartParameters object is responsible for validating the user's choices. The NewChartViewController needs to manipulate the view to keep it in sync with the validation result. (Avoid letting the user make a mistake: don't wait until the end to validate the input.)
When the view finishes, the NewChartViewController asks the model to create a new chart using the given parameters:
[self.document.workbook addChartWithParameters:self.chartParameters]
If you want the not-yet-a-chart object to be part of your document, you can do is this way instead:
EditorWindowController asks document model to create a new chart object:
Chart *newChart = [self.document.workbook addChart]
Thew new chart should have a flag set, indicating it's not ready for display.
EditorWindowController sets up the NewChartViewController, passes it the chart, displays the window.
Chart object validates the users's choices and the NewChartViewController keeps the view in sync.
When finished, tell the chart it's ready for display. Or if the user cancels, remove it.
In either of these designs, NewChartViewController is a model-controller and view-controller in one, localized for its particular task.

MVC pattern and model object initialization in Cocoa

If I am using an instance of NSArray to populate a pop-up button, where in terms of MVC does that NSArray need to be initialised? I'm guessing it would fall under Model, however if that's the case, how do I initialise the array? Do I start a new implementation file to contain the array? (Obviously don't want to use my app delegate file as that would fall under Controller, not Model.)
The "model" part of MVC is the data that the app stores, presents, and/or allows the user to manipulate. It would largely be the same whether your app was running on a Mac, an iPhone or whatever. The "view" is the UI. That is the things the user actually sees on screen. The controller is the part that goes in between these two. It's responsible for implementing the specific behavioral logic for the app as well as "gluing" the view layer to the model layer.
So, with that said, the array of items to be displayed in a popup button may or may not be part of the model. It entirely depends on the specific UI you're implementing. If the selection is between a number of objects represented in the model, the array's contents would indeed be part of the model, but it still might be that the controller pulls the items out of the model in another form and turns them into an NSArray. It might also be a way to select between e.g. a fixed list of actions to be performed, in which case it's more properly part of the controller layer itself.
In other words, there's no one answer to your question. But, the likelihood is that the controller will at least provide the array in question to the UI, and may also be entirely responsible for its content. It all depends on exactly what you're trying to accomplish.
The initialization would happen within the model object, but that initialization would likely be called from a view controller (I wish these were just called controllers--there's no ModelController class.) Possibly in viewDidLoad but really wherever the best fit for your use case would require.
The model object should initialised by the controller object, usually in the viewDidLoad method. If a model object is owned by another model object (for example, if your custom model object has an NSArray instance variable, then your custom object is the parent and the NSArray is the child), then that child model object should be initialised in the initialised method of the parent model object.
I suppose your NSArray is a model object on its own, so it should be initialised in the viewDidLoad method of the controller object.
This is just one answer and not necessarily how everyone develop applications in objective C.
If I have an app with a small data model or with models scoped to their views, I will put the models on the AppDelegate or in the viewControllers themselves, if they are limited in scope to that view.
They will be initialized closest to where it makes sense in the app for that data.
Sometimes you will see a "FAT" viewController which represents a home screen controller or main screen controller and folks will pile the models on that class. Its very common.
But if I have an application with a large data model - lots of models that have lifetimes not scoped to the life of a view - then I will create a class in my application called *myAppNameHere*AppModel, and I will centralize the storage of application models, and use service classes as necessary to request data to populate/update models.
This is just one approach. And great question!

Resources