In the MVC model, where does the view differentiate between the model when the views are sufficiently complex?
My question arises from my attempt to develop a desktop application with a Canvas view. The user has a click mode (e.g. select, add object A, add object B, add object C, etc.). When performing actions, this changes data in the model. The state of the model can later be saved to a file via another view control.
When starting the project, I attempted to encapsulate as much of the Canvas-specific state as possible into the Canvas view. However as I attempt to fit the MVC pattern, it seems as though most of it belongs in the model.
I feel as though the Canvas class is complex enough to contain its own state, which is where my confusion arises. It contains the location of several types of objects on the Canvas. Where does the boundary lie between view data and model data? Or is this a case where there is MVC within an MVC (i.e. M V(MVC) C)?
I have chosen MVVM after looking into some patterns. It seems to be exactly what I needed. The ViewModels hold data specific to the views or controls, that will never be saved but still need to be bound to by the UI.
Related
I created a custom NSView that displays some data exactly the way I want it to (a line chart of sorts). I now want to add a couple of sliders to have the ability to zoom the displayed data in and out. I would also like to add a couple of checkboxes so that the incoming data can be interpreted and graphed in different ways, and maybe some scrollbars to be able to see past data. I need to have at least 5 copies of this view (with all its controls) on screen at the same time, each showing a different data feed.
This way of thinking a user interface falls nicely into the WebComponents paradigm where you can design a component that encapsulates many different ones. As I understand it, there is no way of nesting controls like this into a master control in Xcode.
Of course I could layout all the views and all the controls separately inside a view controller and achieve exactly what I want but it would not be as maintainable as having ONE object that I can duplicate either in interface builder or in code.
My question is: what is the proper way to achieve this in Xcode (if any)? I don't need code examples but rather a conceptual answer and I'm only interested in answers related to Cocoa rather than CocoaTouch.
I just learned that you can have multiple view controllers as child controllers. This is exactly what I was looking for as it maximizes reusability and reduces maintenance.
I divided the Main View of my VC++6 MFC application using Static Splitting with rows and columns like (1x2) or (3x3) and so on.
One of these parts, when clicked on, is the Active View.
When I draw a shape say, a circle/rectangle on the Active View, all the other Views ape the shapes I drew on the Active View. How do I avoid that?
I tried UpdateAllViews() with the Active View as first argument. It still does the same.
Any ideas?
If you are using the same class for all views this is expected behavior, since splitter wires all views to the same document object. I presume that you are use document object for drawing data storage.
UpdateAllViews is used for to update views if data in the document change. Each view then uses document’s data to render different visual interpretation of this data. Hence each view would be a different type (represented by different classes) knowing how to visualize data.
For example: document is used to store number array. Three views are showing those numbers as decimal, hex and binary representation.
If one number is changed, all views are notify to update own representation.
In your case working solution would be to move drawing data to the view rather than the document. Most likely your application does not need a document at all.
UpdateAllViews() calls the OnUpdate() function for each view. The default implementation of OnUpdate() invalidates the client area (talking about simple "graphics" views like CView() or CScrollView()). You can override the OnUpdate() member and encode the desired behaviour (as far as invalidating/updating is concerned) in the lHint and/or pHint parameters.
I have a window that contains several rather complex views. Right now, I'm using a single NSWindowController to control the UI for the window and all the views. It's becoming a pretty huge class, since it's dealing with the details of each and every view.
The view behaviors are independent from one another though, so I see an opportunity to put the UI logic for each view into a separate controller.
According to the Mac App Programming Guide, this is exactly what view controllers are for:
Use view controllers to divide up the work for managing more
sophisticated window layouts. Your view controllers work together
(with the window controller) to present the window contents.
However, I can't find any documentation or examples on how this idea works in practice. Can I add multiple view controllers to the nib file in addition to the window controller?
If you add the view controllers to the nib, that's where they're going to be instantiated, and you'd add IBOutlets to the window controller (assuming that's the nib's File's Owner) in order to connect them.
In terms of memory, however, that scheme could become expensive, especially the more view controllers you have. You may want to instead consider lazily instantiating them in the window controller, (i.e., doing so only when needed), assuming this doesn't result in an objectionable lag before the view is presented for the first time.
Don't be afraid to try both approaches. One of them may be best for you.
In any case, I applaud you for your decision to factor out all that code into separate controllers. Very nice. Good luck to you in your endeavors.
In my experience I have only had 2 patterns work for large-scale desktop application development when trying to keep the model and UI in sync.
1-An eventbus approach via a shared eventbus command objects are fired (ie:UserDemographicsUpdatedEvent) and have various parts of the UI update if they are bound to the same user object updated in this event.
2-Attempt to bind the UI directly to the model adding listeners to the model itself as needed. I find this approach rather clunky as it pollutes the domain model.
Does anybody have other suggestions? In a web application with something like JSP binding to the model is easy as you ussually only care about the state of the model at the time your request comes in, not so in a desktop type application.
Any ideas?
I am currently using the event bus approach to synchronize the models and the UI in my application, but I have hit a hurdle with it in that it's difficult to make it very fine grained, for example, at the property level where you are just interested in knowing if property x of an object gets updated, and there are hundreds or thousands of such cases.
For such a fine grained control, you might want to checkout how KVC (Key Value Coding) and KVO (Key Value observing) works in Cocoa. It basically allows an object to observe any other object's properties as long as it uses some basic principles of KVC. The interested objects automatically get notified upon changes, and you don't have to explicitly notify the observing objects on each property change as that is taken care of by the underlying implementation of KVO. It is somewhat similar to the PropertyChange listeners in Java beans.
If there is too many observations going on, and writing the glue code to update models/views on property changes becomes problematic, you might want to take it a step further and have data-binding to keep models and views synchronized. Built upon the concepts of KVO, the idea is to bind properties of objects, so that a change in one automatically updates the other, and vice versa. For example, you could bind the text in SO's answer field, to the answer preview that we see right below.
.bind('answer.value', 'answerPreview.text')
Both happen to be view elements in this case, so data-binding is a generic approach, and can be used to bind objects more appropriately and not just UI with models.
The idea of MVC itself seems clear to me but I have trouble understanding how the concept 'scales up' to multiple views and controllers.
It appears that Cocoa takes the approach of the controller being the 'switchboard' between the model and the view. How would the application be organized and function in case of multiple views? If there is a controller associated with every view, would the main application have to keep track of all the controllers it spawns, or each controller would have 'nested' controllers it instantiates, e.g. an application would create a window, the window would create a toolbar etc?
What if the entire application would need to work with the same model, or would you break the models down into smaller ones?
It seems like what I'm really asking is how you would split a multi-window/view application into its logical blocks while retaining the modular MVC structure. I've attempted to look at code from the WordPress iPhone app as well as Adium but both seem to have a relatively large code base that I get lost in.
Generally controllers are implemented hierarchically. For example, in the standard Cocoa Document architecture, you have an NSDocumentController that manages multiple instances of NSDocument. Each instance of NSDocument manages one or more instances of NSWindowController, and each instance of NSWindowController can manage one or more instances of NSViewController.
As you move down the hierarchy, the controllers become more specific and fine-grained in their responsibilities. In terms of accessing the model, Cocoa has several patterns such as the delegate and datasource patterns which you can use to allow the view to draw without the view needing to know anything about the model itself.
Generally the app would have a single unified model, unless it makes sense to have different models (for example, if you needed your app to edit different types of document).