i have a class RequestHandler that takes the requests for some ViewController and fetches data on the web asynchronously. In order to notify the ViewController, it implements a protocol and the ViewController is set as its delegate.
Now, this ViewController is a TableViewController, and when a row is selected, it pushes a second ViewController on the NavigationStack. This second (child) ViewController needs to use the RequestHandler too. How can i make it a delegate for the same RequestHandler instance? And how can i make sure it won't mess with the parent TableViewController once i go back to it?
The fact that both view controller would want the same request suggests a design error. The view controllers should display the current state of the Model. They should not directly deal with active network requests.
You should have some group of classes that represent your data. These are called the Model. View controllers should only care about the model while the view is onscreen. So a reasonable pattern looks like this:
ViewController registers for notifications of changes in the Model
ViewController updates view with current data from Model.
ViewController requests an update.
RequestManager (singleton) creates a new RequestHandler to process it.
When RequestHandler finishes, it tells RequestManager and is released.
RequestManager updates Model with new data
Model alerts registered observers that it has changed.
ViewController updates view with current data from Model.
Now it doesn't matter if the user is on this view, or has moved to another, or moves to another and comes back. In call cases, any time the model changes, the current view is updated.
If I understand you correctly, is the RequestHandler a class written by you, so you could allow it to take more than one delegates for the implemented protocol (just store the delegates in an NSMutableArray, so you can add reps. remove them as you need)
Now when the new view is created, you can just 'register' it to your RequestHandler. The same way if the view is going to be closed, you could/should deregister it from your RequestHandler.
Related
I am developing one navigation based application. All data required for each screen are getting downladed from webserver. I am starting downloading in viewDidLoad method. ALl downloadinh is happening asynchroniously and respective viewcontroller will receive data through delegate pattern. Now my question is in case new viewcontroller is getting pushed on navigation stack or current view controller is getting popped off so fast before data will get received, how we will handle this situation? We do not want to block UI so user can move back or forward. I used notification mechanism to detect particular view controller (one who receive data ) is alive or not , but it seems like not a concrete solution. So basically I want to detect receiver is appropriate for receiving downloaded data before I make a call to its delegate method.
Any pointer related to it is highly appreciable.
Thanks!
Nilesh
I think the dataSource pattern is more appropriate.
1) Create a datasource (singleton or attached in your app delegate)
2) Implement a method dataWithPredicate: (or just data)
3) Notify your viewController (with NSNotificationCenter) when a data is updated
4) Reload data from the controller (with dataWithPredicate: call)
Another way is to use core data for that. CoreData generate all the notification and do the job for you.
I'm currently developing an iPhone app communicating via REST with a web server.
Each time the app starts it checks for remote data updates. If the data has not been loaded I start an async request in the app delegates applicationDidBecomeActive and show a modal progress view while the request is running. Some of my view controllers also need a data update which should be handled while the same progress view is visible and after the first request has finished.
What is the best approach to handle this scenario? Post a notification to the view controllers after the first request has finished and call back the delegate to dismiss the progress view?
Or is this considered a bad solution?
Best Regards
Carsten
Posting a notification should be used if the sender does not know anything about (should not depend on) the observers. For example, data object posts notification when it changes, so the visual objects connected to it could update themselves.
In your case you need to have a root object, the owner of your view controllers. It may be your Application Delegate or a subclass of a Navigation Controller. Since the owner knows about the view controllers, it can directly tell them to update when the request finishes.
Generally, do not send notifications between the owner and its dependants. Owners can directly call dependants' methods. Dependants can have weak links to their owners and let them know when they update. If you need to make dependants independent on the owner's class, define a delegate protocol.
I'm new to programming, iphone application programming in specific. After reading a bunch about MVC I decided to give it a try in a small application. As to my understanding, MVC works like this:
Model: data, manipulating data, retrieving data.
ViewController: formats data from the model (NSDate to specific style), etc.
View: the actual gui.
If this is indeed a correct formulation of basic MVC theory, my confusion lies in how data is passed between the model, VC, and view. Example: if I make calls to twitter and get the data in the model, how do I (correctly) pass this information to the VC for further work. I know that between the VC and View one mostly uses IBOutlets. The Model is my real problem.
In my last app I made an NSString variable in the app delegate so I could access that data from any class. However, I read that this is not the best approach when the app becomes complex because the delegate is in charge of starting, ending the app, not holding data.
I've read of delegation methods, singleton's, NSNotification (which I've used to call methods in other classes). The problem is that I don't really understand how to use these techniques to pass data from the model to other views.
Please let me know if my question is unclear.
If you think about reusability, the main components that can be reused again are your model objects and view objects. They can be moved to different apps and still used properly. Your view controller is what is really specific to your app and where most of the app logic lies.
So in your example, you could have a twitter object that stores information and tweets from a user perhaps. You would create that class with all its functions separately within its own .h and .m file. Then in your view controller, instantiate the twitter class with data that is retrieved and begin using it from within the view controller.
Your view controller is actually retrieving the data but your model object is the one maintaining the data. In this way, you can pass on the model data with your twitter object to other view controllers.
Control over the application resides in the controller, so it is the object that will retrieve or save persisted data, update views with that data, and handle various events. Consider it the glue between the model and the view!
For example, if you were to click on a button to open a new modal view, you'd handle that event in your view controller. In the method that responds to the clicked button, you will create or access the new view controller and present it using presentModalViewController:animated:. If that new view and controller needs data that your current controller has access to, you could set a property in the new controller to refer to the object.
I have a view controller which gets an NSObject conforming to a protocol and then displays a view with the object's properties.
The question : How can my controller know that a property of this object has been modified and then refresh the view ?
Thanks a lot
Thierry
There are three ways of doing this:
Have the object call a method in the controller in response to an event e.g. a user clicking the button. This is usually done using an IBAction.
Set the controller to be the delegate of object e.g. a UIWebView sends a message to its delegate when it finishes loading a page.
Use a notification. The object generates the notification and then one or more objects (including the controller) registers to listen for the notification. This is usually not used with interface elements although it can be.
I can't tell you more without more detail about the specifics of your project.
Your viewcontroller should conform to your .
In your model, all your set methods should trigger appropriate functions you define in your modelchangedprotocol.
This OO design pattern is also known as "Observer" design pattern.
I have following problem:
I have built a tabbar application with 4 tabs. I want to pass a object/variable from the first tab controller to the third one and initialize this controller with the corresponding object.
I've already done some research. The best way, corresponding to a clean model approach, would be to call some initWithObject: method on the called viewcontroller.
How can I achieve this? How can I call the init method of the receivercontroller within the callercontroller? Can you give me some code example?
Edit:
To pass data between several views/classes etc simply create some Kind of data class which holds the data beeing shared between several classes. For more information follow the link:
Singleton
You need a data model object that stores the data for application.
A data model is a customized, standalone object accessible from anywhere in the application. The data model object knows nothing about any views or view controllers. It just stores data and the logical relationships between that data.
When different parts of the app need to write or read data, they write and read to the data model. In your case, view1 would save its data to the data model when it unloads and then view2 would read that data from the data model when it loads (or vice versa.)
In a properly designed app, no two view controllers should have access to the internal data of another controller. (The only reason a view controllers needs to know of the existence of another controller is if it has to trigger the loading of that other controller.)
The quick and dirty way to create a data model is to add attributes to the app delegate and then call the app delegate from the view controllers using:
YourAppDelegateClass *appDelegate = [[UIApplication sharedApplication] delegate];
myLocalProperty = appDelegate.someDataModelProperty;
This will work for small project but as your data grows complex, you should create a dedicated class for your data model.
Edit:
To clarify for your specific case, you would add the call to the data model when the receiver viewController becomes active.
Placing the data in an init method or a viewDidLoad won't work because in a UITabBar the users can switch back and forth without unloading the view or reinitializing the view controller.
The best place to retrieve changing data is in the viewWillAppear controller method. That way the data will be updated every time the user switches to that tab.
You might want to consider NSNotificationCenter (Reference); you register the one viewcontroller with the application notification center, and send a notification when a selection is made. When the notification is received, the other viewcontroller updates itself accordingly.
I don't think this is best practice (also check syntax) however I have got away with:
in the .h
otherclassref *otherclassname
#property (assign) otherclassname otherclassref;
and in the .m
#synthesize otherclassref;
then I just assign the reference from somewhere convenient e.g. the app delegate or wherever you are instantiating your viewcontrollers.
then the view controller can get a reference to the other view controller.
I add #class secondviewcontroller to the .h file for the firstviewcontroller and put put the #imports "secondviewcontroller.h" in the .m file of the first view controller. These are called forward references and prevent compiler errors resulting from having .h files referencing each other.