I have a project that will have a lot of views (20 in total). They are displayed in sequence and the user makes certain decisions before tapping a button to make the next view appear. When all 20 views have been displayed, it goes back to the first view.
I also need to create a lot of instances of 3 different objects. So there may be 40 different instances of object1, 20 of object2, and 30 of object3. Each view needs to know about all of these instances and will often change instance variables.
I need to pass these instances between the views. I think I will do this by passing a pointer along to the next view. My question (I've finally got there), is where to create all these instances in the first place? In the original View Controller? Or in the AppDelegate?
Many thanks for any pointers (pun intended)
Usually you'd use CoreData for this. You start creating objects in initial view controller. Then after user manipulates the object you pass that object into next view controller (probably via UINavigationController) and create appropriate objects there as needed and so on and so forth.
On a side note - please rethink your navigation flow and user experience. User might be tired enough after as little as 5th configuration view.
Think MVC
When designing the model, consider diferent aproaches: CoreData, serialization in filesystem, in memory using singletone...
And remember: load lazily
Related
I am badly struck in a issue where I am trying to populate the nestableview lazily. Below is my approach.
I have created a custom class PRIList where it has an instance of array to manage the models.
I have bound the priList.items to the array controller in the xib where items is not an instance in PRIList but to support lazy loading I have implemented the methods countOfItems and objectInItemsAtIndex:.
Initialy when I populate the PRIList I populate few objects (say 50) with valid objects and rest with the faulty objects. In the objectInItemsAtIndex I check if the item at particular index is valid or faulty. If it is faulty I fetch next set of 50 objects.
What I understand is NSArrayController calls the method objectInItemsAtIndex for only the visible rows in the table view. But the problem here is as soon as set the PRIList the objectInItemsAtIndex method is called for all the objects. This is even called when some selection is changed in table view (the stack trace shows this method is called from [_NSModelObservingTracker startObservingModelObjectAtReferenceIndex])
Basically I want to fetch the records whenever the user scrolls down in the table view.
I followed the same approach in a different project in Lion. It worked there. Currently I am in Mavericks.
I tried overriding the isCompatibleWithResponsiveScrolling in the custom table view and returned it to NO. Still no luck.
Any help is very much appreciated.
First, have you assigned or bound the sort descriptors of the array controller? Or set any columns to automatically generate sort descriptors? (I'm not sure that latter is relevant. It depends on whether the column is sorted by default.)
In any case, if the array controller feels the need to sort the objects in order to arrange the objects, then it will need to load all of the contents. I was under the impression that it always does so, anyway, although you report that it works.
For an issue like this, I'd recommend that you go for full manual control. That means not using bindings or an array controller. Use a data source.
I have a view controller placeViewController which pulls in a bunch of Place objects, and from these loads and populates a matching bunch of PlaceView objects which are then displayed as subviews to its main view.
I need to update these views periodically which requires information from the model and other places to be pushed into the views
How should I properly structure this?
Keep an array of Place objects and give the model a PlaceView property to store pointers to the views
Keep an array of PlaceView objects and give the view a Place property to store pointers to the places
Keep both arrays and use a lot of indexOfObject objectAtIndex to jump between them
Some other way??
I need to update these views periodically which requires information
from the model and other places to be pushed into the views
You should really focus on an ObserverPattern. Yours views register to "notifications", and when changes are made, your registered views are notified.
http://en.wikipedia.org/wiki/Observer_pattern
You still can use NSNotificationCenter, but it will not futfill your needs since you need yours views make update per Place object (paired like a dictionary). So i recommend you to implement your own.
It will loose coupled because your controller will just only make glue between the observer and your views, and all the "logic" will be handled by the observer.
Well basvk got the answer in his comment but hasn't posted an actual answer for me to mark correct.
So here it is: "I would create a NSMutableArray with PlaceView objects. And the PlaceView class holds a #property Place *place"
In MVC the View shouldn't hold it's data. However I know in Objective-c you do: [textField setString:#"hello"];, that string is then retained by the text field. The same applies for the textField's font and text colour, etc.
However a UITableView uses a datasource to ask a controller for it's data, it's then up to the controller to reload the table view. But it also stores some data itself, like background colour.
I can understand a reason as to why a UITextView doesn't use a data source the code would become much more lengthy, if every property had to be a method. But why use a data source in some cases and not others, why not just set an array of UITableViewCells (I know that this means cells could not be reused and so it would use more memory, but what other design reason is there), for the UITableView to display?
And when creating you own objects how do you know when to just store a small amount of generic data (e.g. the string a textview displays can only be a string, but any the string itself can be anything)in a view, or use a datasource?
MVC is a pattern, not an edict. Let the view do the work. Some coupling is just going to happen. Follow the guidelines of the pattern, and bend it to the style and desires of your developers and organization.
I'm not familiar with objective-c's mvc framework, but I think I understand the question.
Basically, you don't want the view doing anything with the datasource backend, that is, anything having to do with the plumbing of accessing the DB.
But its ok for the view to have access and use the data itself. That is the M part of MVC. The model gets passed around. The view knows how to display it. The controller knows how to do the business logic to it (including interacting with backend systems like the data access layer).
In the case of data grid, it has to hit the backend to get the data, so it has to rely on the controller.
Ideally, the view knows only about display related information (like the background color). The whole idea being separation of concerns. You want the view to handle just its part of things, like-wise the controller. Then you can modify them independently of each-other.
As for the specifics of the datasource (versus an array), grids tend to be complex. Maybe that is handling paging or other niceties. In this case, I don't think its so much the separation of layers (since an array could just as easily be the model), but handling more functionality.
I'm not sure what you mean re 'storing' small amounts of data in the view. The view should tend to deal with 'view stuff'.
I'm attempting to do a better job of keeping my data and my visual representation of data separate in a new project and I'm having some trouble with the abstraction.
I have a list of objects in a set that are part of an inventory and I use that data to generate some UIImageViews that get placed into the interface, thus keeping my models and views separate. When a user taps on the UIImageView, I want to be able to take an action on the data in the set as well as modifying the corresponding view.
How do I keep track of the object that is being represented by the UIImageView? I would think there's some sort of mechanism by which I can say "here's a reference to the object that you represent" but I can't figure out if that exists or if there's a more accepted way to achieve the view/model separation.
you could create and object that is an extension of the ImageView and upon initialization of that view, associate a property in the view to your data associated with the view.
My app requires an interface that has many buttons, text fields and matrixes. And they need to change from time to time. Right now I do this by having all elements in IB already and hiding/showing/moving them when needed. What would others recommend? Should I do that? Should I use an NSTabView? NSView? Should create the elements programatically? If so, what if I have an element that is already created that I need again without changes? It would be a waste of releasing it and creating it again.
Any help would be greatly appreciated.
In my opinion, it's better to create interfaces programmatically if you have to animate views around a lot. If it's just a matter of hiding/unhiding them, IB works great, but if you need re-layout or create unknown numbers of views dynamically it's not worth trying to make it all work with nib files.
As for general advice:
Create subclasses (from UIView or UIControl or one of their subclasses) for every kind of element you're going to use. It's tempting to piece together composite views from your UIViewController, but you'll really be much better off creating real classes.
Study the standard Cocoa view classes, and try to create similar API:s in your own controls and views.
Put as much data (sub-element positioning etc) into a plist, so that you can easily change it from one centralized place instead of having to dig around in the code.
If you are often creating several dozen short-lived views, it's worth keeping them in a pool and reusing them. But if it's just a few labels being added and removed intermittently I wouldn't worry too much about it. As usual: don't optimize too early.
Your current approach sounds fine. If you're showing/hiding them but otherwise they remain unchanged, why go through the trouble of creating them with code, when your XIB keeps a "freeze-dried" copy of exactly what you need already?
As long as you're keeping them within logical groups, you can just move/swap/show/hide the group's container (like NSBox or an NSView). If you have a LOT of logical groups, which aren't always shown every session, you can separate them out into their own XIBs and only load them when they're needed, to save launch time and memory.
If you use NSViewController, it's even better because you can make clean breaks for each logical group. Load the panel as the view and the view controller will keep outlets/actions and has a one-to-one relationship with a xib.