How can I get a method to call in a class while the user is in a view of another class? - iphone

I have an iPhone app based on a tabBar and tableViews. I want the user to be able to click on one tab and access options for filtering the data in the initial tableView.
The problem I'm having is that while the user is selecting filter criteria, I want the main table (not visible) to update. The reason this is important is that I want to show how many cells are still in the table as it is being filtered in the navigation bar.
Currently, the method for filtering the main table (-handleFilter) is called in the viewWillAppear method of my rootViewController class. How can I call this method from my "searchOptions" class?
Thanks for the help!

It sounds like you're conflating too much between your model and your controllers (assuming you're following the MVC design pattern). The other controllers besides the main table should be able to query the model themselves to display the count information without asking the main table controller.
I could be misunderstanding something though, a little more information on what data you're using and how it's being filtered in the controllers attached to the other tab bar items would help.

The most straightforward way would be to give the options controller a pointer to the list controller. Then you can call the method directly.
Other options include defining a method/property on some global object (like your app delegate) to access the list controller from elsewhere in the app, and using a more decentralized mechanism like NSNotificationCenter to pass that information around (rather an a method call), or relying on the model itself to notify all of the controllers accessing it when it changes (possibly using Key-Value Observing, or an explicit delegate protocol).

Related

retain entries in UITableView

I have the following (view) controller arrangement:
an uitableview --(embedded in)--> navigation controller --(embedded in)--> Tab bar controller --(modal segue to)--> button in a view (uiviewcontroller).
description of my problem:
The view with the button is the initial view of my app. Pressing this button leads to a tableview in a tab bar. At the beginning the table view is empty, but you can manually add information on the cells, like names. However, once you go back to initial view (with button) and press the button again, the previous entries in the table view are erased.Can somebody give a hint how to retain these entries with the given arrangement. Thank you very much in advance.
You can use the singleton pattern. It will create a shared instance of your object, that you can access anywhere. You will then be able to write in it when the user adds a row in the table, and read it when you come to the tableView.
Here is a bit of help : Singleton pattern
EDIT : you can also use core data, but it may not be appropriate in your situation (plenty of docs on the web about that one)
This is quite a question as it really isn't about the interface per se. It is more to do with general Object Orientated Programming and the life time of objects.
Basically your data needs to be stored higher up the object hierarchy. It needs to persist across construction/destruction of the interface objects. This could also be done by storing the data in persist-able data store such as a DB or file but you would still need to store the means to extract the data or subset of data from the store.
If you wish to persist the data you could store data in a singleton data class and reference it statically or store it in your UIApplication object and pass that down the hierarchy as you create each object. you would probably have to subclass each object and add a new constructor passing in a ref to the data.

where to store main table view data? (appDelegate or rootViewController)

Any advice on where to store the main list data for an iPhone application like the following?
NavigationController based
Level 1 (main screen) is a List of Items. Hence it uses a table view (table of items)
Level 2_EDIT: Is a view you can get to from the main screen by clicking EDIT. Here you can add text to be added to the main view list
Level 2_DETAIL: Is a view you can get to from the main screen by clicking on a cell.
Now assuming the implementation is (rough overview):
* MainView - appDelegate (holds UIWindow & UINavigationController)
* RootViewController - table view of the main items list (? variables here ?)
* EditViewController - input text to add to main list
* DetailViewController - shows detail of record
Question - Where to hold the NSArray that keeps the main list of items? Should it be in the RootViewController where the Table View exists that displays it? Or should it be higher up in the ApplicationDelegate? I note that when you go from RootViewController to EditViewController, then in this edit view you would have to ADD items to the array, so would it be easier for the code in the EditViewController to access the main array from the AppDelegate (as opposed to the RootViewController)?
(Note - still haven't made an app that has a specific model object, re MVC, yet, so not sure if this should come into the picture.)
Your data becomes the table view's data source, and although it doesn't have to, the view controller that contains the table view often does the data source's role. The view controller can also be a delegate for the EditViewController, so the EditViewController sends a message to it so it can update the array.
Apple's CoreDataBooks sample project show similar architecture. You may want to take a look.
Having the array in the application delegate is often not a great idea. Although it can give you a little bit of convenience, now your classes totally depend on your application delegate unnecessarily.
Your table view shows your data. This corresponds to View in the MVC design pattern. I assume RootViewController is the view controller of the table view, which acts as a Controller in the pattern. Your data, the location of which is not decided yet, corresponds to Model. The role of RootViewController becomes connecting the Model and View.
The ideal, or the reason of the MVC pattern is to isolate the model and the view, so the model can work with other views with appropriate controllers, and the view can also work with other models with appropriate controllers. For example, your RootViewController will provide the table view with data. It will specify the data in the language of table view, e.g. the number of sections and rows, the contents of cells, etc. If you want to present the data in a different way, for example a graph, your controller will access the same data (model) and provide the graph view with a different representation of the same data. The model need not change, neither do the views. You write only the controller, for each combination of a model and a view.
Ideally, therefore, you will have a different class for the model. In this class, you will store the array, and provide a general interface for controllers can interact with the data.
However, it's often not that necessary, either because it's unlikely that you will use the model class often again, or because the model itself is way too simple so it can be easily implemented anywhere. For example, if your data for the table is a simple array, an NSArray object is often sufficient for the model's role. Therefor, here comes an idea that to combine the controller and the model into a single object.
This is why it makes sense that your table view controller often acts as the data source of the table view.
However, storing the data in the application delegate is a completely different idea. Now the application delegate becomes your model, but which does not make sense, because the application delegate is only used for the specific application. Why would you have a separate model object that totally depends on a single application? Also, if your table view directly interacts with the application delegate, it means that now your view cannot work for other applications either because it now depends on the specific application's application delegate.
Often the reason why people are tempted to have data in the application delegate is, that the application delegate is easily accessible by any objects in the application by using [UIApplication sharedApplication].delegate. The M-V-C relationship is not always very simple. For example, your EditViewController also need to access the same model. To do this, you have to write some code to make the model accessible by both the table view and the edit view. If you have the data in the application delegate, you don't need to do anything, because you can magically access the array by accessing the application delegate.
But that's all. A few minute's saving in your coding time, for the price of ruining your software architecture. I'm not a fundamentalist, and I do sometimes use application delegate to store some data when I'm absolutely sure that it's not worth to provide well-formed interfaces, but it's rare.
So how should you connect your edit view to the data merged into the table view controller? There could be multiple ways. What I suggested before is let the edit view controller has a weak reference to the table view controller (delegate) and send a defined message, for example - (void)editViewController:(EditViewController *editViewController) didFinishEditing:(id) someData. In this way, you can use this edit view controller with some other view controllers as long as they use the same protocol. But others may implement different interfaces for it.
You need to store in the appDelegate,as you can acees the data in anyviewcontroller then.But if you use rootviewController,then you can only send data to next ViewController then,not to the 2nd or 3rd ViewController directly.
Hope it will help you.
Good Luck

iPhone programming guideline : List / detail / modify

I have a program that displays a list (a TableView).
When the user clicks an item, it's detail is shown.
On the detail view, the user can ask to modify it so a modify window is shown.
Here, the user can ask to delete the item.
I would like at this time return to the list with the item deleted from the list and from the data source.
There may be thousands of methods to do this, but I wonder which is the best / good one.
Could you help me, and/or give me a good reference to read about this ?
I think he ask how to get from view number 3 back to first view.
Then you can put your three views inside a UINavigationController and call on the last view popToRootViewControllerAnimated:
at least Two options:
Delegation - Create a protocol called something like: TableDetailModifierDelegat
and add methods like modifierDidChangedItem:(id)item
or modifierDidDeleteItem:(id)item
and to the modifying view controller add instance variable id so when you done editing or deleting you will call the appropriate methods.
of course you will need to make your table view controller implement the protocol you created. if you modified or deleted an item you should update your data source and reload the data to the table.
also pass the Table View Controller as the delegate when creating the Modifying View Controller.
Passing The Data Model.
This is much more simple to implement.
you can simply pass your data model to the modifying view controller, and make the changes directly to the data model.
You should keep the data model as Instance Variable in the modifying view controller.
when you done, dont forget to reload the data to your table.
In this instance, you could simply remove the data from the data source the UITableView is using and then call the reloadData method on the table. (As you're editing the data in question, you'll presumably have a suitable method/reference by which to delete it.)
As a bit of reading, I'd recommend Apple's Table View Programming Guide for iOS - this provides a lot of useful background information.

How to access other view controllers data member variables?

I want to access the value of a view controller data member variables in another view controller object.
Or is it possible to access its controls like UILabel text property?
A lot of times when I find I have to do things like that I find I can redesign the solution and the need for it goes away. Jay's law: "If it's too hard you're probably doing it wrong."
It is possible to access a UILabel of another view controller, but don't. It will lead you to very hard-to-understand bugs. Any IBOutlet can become nil at surprising times when memory is low. You shouldn't mess with another object's UI elements directly.
Your initial idea of accessing the data (model) objects, is the right one, though generally you will be better off to just initialize both view controllers with the same model object. For instance, say you have a status message that you want to show up in two different UILabels in two different view controllers. Rather than have one view controller ask the other view controller for the data, it's better to have a model class like "Status" that both views have a pointer to. Whenever it changes, they change their UILabel.
Even better is to post a notification (StatusDidChangeNotification) and just let everyone who cares observe it and update their UI appropriately.
You want to keep UI elements very loosely coupled in Cocoa. Otherwise you wind up with hard-to-fix bugs when you make what seems like a minor UI change.
You are going to have to define the property in the view controllers interface, then as long as you have a reference to the view controller in the second view controller you should be able to access it like the text of a UILabel..
viewWillAppear: is only called by the framework when you use the built-in view controller transitions like presentModalViewController:animated: or pushViewController:animated:. In other cases, you have to call viewWill/Did(Dis)Appear: yourself.

Passing data from modal navigation controller to parent controller?

I'm starting out in iPhone development, and I'm trying to do a Contacts-style controller to add items to a table. I've got the two controllers designed, but I can't seem to figure out how to pass data between them. How can I get data from the modal controller to its parent?
Just trying to call methods on parentViewController won't work (and results in compiler warnings and crashes). I've considered moving the data out of the controller itself (which is going to happen anyway, I'm just trying to keep things as simple as possible for now), but even then I still have to somehow tell the parent view to refresh its data. Again, how can I do this?
I've considered moving the data out of the controller itself (which is going to happen anyway
I think now may be the time to follow that consideration and create a separate "ContactList" model object to store your data.
Your modal view controller just adds new "Contacts" into the "ContactList".
Your TableViewController should observe the same "ContactList". As items are added/removed to/from the "ContactList" your TableViewController will simply add and remove rows from its tableView.
In this way you will keep each ViewController independent, your code will be more flexible and adding/removing single rows will be much more efficient than reloading an entire tableView.
You either keep a link to the sub view you create and ask it for data that has changed on return, or else ad yourself as a delegate of a subview and have it call you back directly (which does work if you have a valid reference).
I had the same question and found this sample code: http://developer.apple.com/iphone/library/samplecode/LocateMe/Introduction/Intro.html
Helped me a ton and was pretty easy to figure out from the code.
In short, use delegate.
I would suggest you have a look at Lecture 11: Text input, Presenting content modally (May 6) - iPhone App Programming course offered by Stanford. Search for it on iTunes U.
Download this sample app if you want to know how to implement delegate: http://www.stanford.edu/class/cs193p/downloads/11-Pickers.zip