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.
Related
In order to explain what problem I am having I will quickly explain the scenario. I have a synthesizer I am building that has several "control views". One control view may be 4 vertical sliders while another is one big matrix or something.. So, say I have control views 1-4. In addition, I have two main sections (which are just holder views), which can contain one of the 4 control views. At any given moment, sectionA can have controlView4 while sectionB can have controlView2. This works perfectly.
The problem with this is SectionA cannot have ControlView1 while SectionB has ControlView1 simultaneously. This leads to undesirable behavior. For example, if SectionA currently has ControlView1 while SectionB has ControlView4 (which will wrap around to ControlView1 on the next toggle), than the next time I toggle SectionB's active ControlView, SectionA's ControlView will simply disappear. (presumably because UIKit implicitly removes it from SectionA's subviews when I add it as a SectionB's subview.)
So, there is some default behavior of UIView that isn't ideal for this modular scheme I wish to implement. That being said, is there a way to achieve what I want without deviating to far afield from iOS best practices and sane code design?
First, I would want to have a different type of view controller for each type of view. Then, each time I wanted a view in a section, I would create its matching controller and have it take over that container area. If the four sections are then displaying multiple copies of the same view, they each have their own controller to keep them organized.
Assuming you have your data model separate from your views and controllers, there should be no extra complexity.
Fairly new to Mac and XCode 3.2.6 and iPad. I have a fairly simple business data model to implement on the iPad, but can't seem to find the combination of views and controllers to use.
It's a simple data collection program, but there are too many data fields to fit on a single screen so I've resorted to the Split View approach.
I've got eight rows of table data on the left; RootViewController is the default UITableViewController. I'm trying to write the program such that when any of those table rows are selected, the view on the right (Detail View) gets redrawn and populated with a bunch of different controls (labels, buttons, text fields, etc.) that correspond to the selection on the left. Currently all the Details views are plain UIViewControllers.
For instance, the first "tab" might be titled "Personal", and I need to display fields to collect info such as Name, DOB, Height, Weight, etc. The next one might be "Address" where I need to collect Street, City, ZIP Code, etc. The next one might be "Employer", where I'd like to collect the employer's name, address, phone number, etc. These are mostly static and unchanging, but there are enough fields for about 8 screens worth.
I've got all this laid out in Interface Builder, but when I run it on the iPad simulator and click the very first button on the very first view, the connected delegate isn't called. I've put a breakpoint there and it's not being hit.
Is there some special magic to using simple UIViewControllers on the right side of a UISplitViewController, as far as letting them contain other simple Label, TextBox, and Button controls?
Also is there any special magic in that the framework built the original start-up code with a RootViewController.h/.m and DetailViewController.h/.m pair? Am I correct in thinking that a single detail view represents the entire iPad screen to the right of the Table View, and that to add more "pages" we need to write more files and .XIBs like DetailViewController?
Final question is how to implement the data model for this app. I noticed when the project was first auto-created, there weren't any source files for the model. (Maybe most of the predefined app types don't auto-generate anything for the model, but I understand that's a big part of model-view-controller paradigm.) Anyway these data fields on all the various views will eventually be part of a SQLite record that I'd like to save and load from storage. Where would I begin to wire all that stuff in to all the auto-generated "view centric" code?
If anyone has seen a "how to write real business apps for the iPad" website along the lines of anything like this, please post the link. I'm not trying to display jpegs of various fruits in a single (reused) view on the right side; I'm trying to display several real controls for real-world data collection for a real business app.
Thanks!
Basic things if you haven't already done them:
Have you connected the interface object the user is pressing from it's INSIDE TOUCH UP event to an IBOUTLET that then refreshes the right side?
If you have, and you've mucked about a bit (ie renaming and moving stuff around), try deleting it from the right-click event panel and then reconnecting it to the same IBOUTLET again (you don't have to delete any code).
Also, if you are counting on some event to fire that isn't firing, you should search on that (ie VIEWDIDLOAD NOT FIRING) because that can both occasionally be "broken" (ie no connection to the Files Owner) but more often one might misunderstand when that actually gets fired (ie VIEWDIDLOAD vs VIEWDIDAPPEAR vs VIEWWILLAPPEAR etc.)
For your data model, CoreData is your friend. It provides a modell-oriented approach and easily allows to persist data.
For your navigation needs, I think a tabBarController better suits your needs.
Changing the detail view from the master view can be troublesome, especially when using a NavigationController as detail view. The best way I've found is using the NSNotificationCenter.
When using UISplitview I strongly recommend to support the iPad only when it's a business requirement - there are some changes in iOs 8 that make easier to use.
I am building a complex iPad application; think of it as a scrapbook.
For the purpose of this question, let's consider a page with two images over it.
My main view displays my doc data rendered as a single UIImage; this because I need to do some global manipulation over them. This is my DisplayView.
When editing I need to instantiate an EditorView with my two images as subviews; this way I can interact with a single image, (rotate it, scale it, move it). When editing is triggered, I hide my DisplayView and show my EditorView.
In a iPhone app, I'd associate each main view (that is, a view filling the screen) to a view controller.
The problem is here there is just one view controller; I've considered passing the EditorView via a modal view controller, but it's not an option (there a complex layout with a mask covering everything and palettes over it; rebuilding it in the EditorView would create duplicate code).
Presently the EditorView incorporates some logic (loads data from the model, invokes some subviews for fine editing, saves data back to the model); EditorView subviews also incorporate some logic (I manipulate images and pass them back to the main EditorView). I feel this logic belongs more to a controller. On the other hand, I am not sure making my only view controller so fat a good idea.
What is the best, cocoa-ish implementation of such a class structure?
Feel free to ask for clarifications.
Cheers.
Huge fat controllers are fine.
If necessary, just break off some "purely logical parts" from it and shove them in other "helper classes". And use tricks like categories extensively where you can.
Definitely go with a HFC (huge fat controller) if that feels right.
Then, just get on your engineering bike and slim the hell out of it!
You should definitely not avoid the right structure, the good structure, the structure you want, just because one thing will be too big.
Just slim that big thing down by outsourcing concepts, going nuts with categories, etc etc - every trick in the book.
My belief!
Some reasons to wrap a viewcontroller around your view:
to use it in an Apple API that requires a viewcontroller (popover views, modal views, navigation bars, tab bars, ...)
because the view can be invisible for a while, and so it makes sense to clean it up in low memory situations. The viewcontroller then guards the data that needs to survive such an unload-reload cycle.
because you just like the MVC pattern
I think the second bullet justifies a viewcontroller for your editable content view and another one for your non-editable content view.
I’m starting to develop my first full-blown Cocoa application containing a view which I would like to behave (and look) similar to Automator’s AMWorkflowView.
The basic features I’d like to achieve:
Positioning of subviews
Display of subviews in expanded / collapsed states
Multiple selection
Drag and drop
In order to get accustomed to Cocoa, I started with a custom NSView which mainly served as a container for the custom subviews and handled their positioning and multiple selection.
The subviews are also subclasses of NSView, and contain a variable amount of views themselves, like buttons, labels and popup menus, and therefore can have different heights.
This worked quite well, but before going on, I want to make sure to have everything neat and tidy according to the MVC pattern.
I suspect that there already is a class in Cocoa that facilitates the implementation of a view container, like maybe NSCollectionView.
It seems that there is no (easy) way to display differently sized views in an NSCollectionView, though. Should I continue implementing my custom NSView (probably using an NSArrayController for selection and sorting support), or are there better ways to go?
Any help is much appreciated
Unfortunately the answer is you'll have to roll your own. NSCollectionView does not allow for variable-sized items (which also rules out expanded/collapsed states).
For a limited number of items, you can accomplish this rather easily (you just need a container view that arranges the subviews properly when asked to layout, then you need to make sure you re-layout when things change). For many subviews, however, you'll need to take care to be as efficient as possible. This can start with laying out as little as possible (only those "after" the resized view, for example) and get as complex as caching a visual representation of a prototype view, drawing the cached images (fast!) for all but the view being edited, and only using/positioning a "real" view for the view being edited.
Drag and drop works the same as it always has, but none of the above accounts for the pretty animation NSCollectionView gives you. :-) It's fast and beautifully-animated precisely because all the subviews are uniform (so the layout calculations are fast and simple). Once you add irregular sizes, the problem becomes significantly more complicated.
The bottom line: If you need variably-sized views, NSCollectionView will not work and you'll need to roll your own or find someone else's shared code, but performance and beautiful animation will not be easy.
As I wire up my first fairly complicated Cocoa-Touch view I feel like I'm inadvertently slipping back into old procedural patterns and finding it difficult to shake them off...Though fully aware of many of the Cocoa (OO) design patterns I'm afraid I may be subverting them.
As such this view in question is quickly becoming unmanageable and I'm wondering if I might be approaching it the wrong way?!? The view is managed by a subclass of UIViewController. The view itself contains ±10 subviews. Some of these subviews "slide" in and out and contain their own subviews (controls, imageviews, etc) that slide along with them.
Without getting into too much detail I've found that I'm executing most (if not all, including animation) of my management code w/in the touchesBegan/Moved/Ended methods of my root View Controller. And it's become a mess of managing, setting & checking boolean properties. if (editingMode & panelAVisible).... if (editingMode & panelBVisible)... or *if (viewFlipped) { for (MyCustomView view in someArrayOfSubviews)} etc, etc... granted the UI of this app requires most of these views (or their contents) to be touched and moved by the user to different parts of the screen.
The main problems I'm trying to solve seems to be along the lines of: if viewA is present then you 3 views go hide (animated)...or, If viewB is touched then all objects contained in viewC are negative... etc.
Any clever (or rudimentary) OO approach to handling this? Perhaps make the subviews that contain views act as their own mini view controllers? I haven't been able to find too many (any?) examples of that though...
As you suggested at the end of your question, I would recommend having a subcontroller whenever you need logic for a particular subview. The point of a controller object is to keep track of state of the view and to encapsulate all that view logic that you were describing. Interface actions, such as if the user can move to a different screen, can invoke save logic, can create a new document, should be in the controller for that particular view. This will help maintain a separation of concerns between the various controllers and cut your convoluted logic down at the top level.
While it doesn't pertain to iPhone programming specifically, the book Cocoa Programming for Mac OS X contains good examples (especially in the chapter about how to do preference windows) of using subcontrollers and subviews in your application.
I think you should go along your last suggestion, make the subviews that contain views act as their own mini view controllers. Each (sub)view that presents a 'screen full of content' could/should be managed by its own view controller.
Animating between those views can be done with the build in navigation controller (you can actually hide the top bar of a navigation controller) such that you have the default slide animation. Otherwise you could indeed create your own animation while still using that navigation controller.
'The view itself contains ±10 subviews'. Some of these subviews "slide" in and out [..]'. These subviews you're talking about are perfect candidates for extraction from your one monolithic UIView.
The basic OO principle to use is how the navigation controller does it, by pushing and popping views on and off a stack. Each view pushed and popped is handled by its own view controller.
HTH
Edit: I now see you're not specifically talking about iPhone development. Still, have a look how its done there (especially the UINavigationController). You can still get the basic design idea