iOS - Updating View Controllers in applicationDidBecomeActive - iphone

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.

Related

Reading/writing to NSStream no matter what ViewController user is in

I am making a very basic iOS chat application, the app now has several different viewControllers so i now somehow want to always listen to the server no matter what viewController the user is on.
Before i had my NSStream code on the viewController that i wanted to update, however now since i have multiple views i want to make sure that the server is listening for updates no matter what viewController a user is on..
How can i do this? Where would i put my methods for listing / writing to the server (so that all viewControllers can read/write to it)?
You could make a global singleton that handles your chat connections and does all the reads and writes. All the view controllers that need to be able to send or receive chat messages would then use that singleton.
For how to communicate between the view controllers and your chat singleton, have a look at Apple's Notification Programming Topics and Key-Value Observing Programming Guide
Don't abuse the AppDelegate for things like that. Just because it is a globally available singleton, does not mean it should handle everything that is shared between view controllers.
Your views should not know anything about chat connections.
Create a singleton to manage the communication. Call it something like XXChatDataController. Be sure that none of the view controllers create their own instance.
If you have multiple view controllers you want to look at using notifications (instead of delegation) to distribute information about new chat data being received as this will allow your code to be simpler and to handle the situation where you have multiple view controllers observing updates at the same time (if you were using child view controllers say).

UIViewController and data receiving issue with Navigation stack

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.

Objective C Callbacks and Notifications

I'm new to Objective-C and not a full time programmer. I'm beginning to understand the Model-View-Controller design pattern for differentiating the UI from the model. So the user takes an action and the view controller sends a message to the delegate (model). But I'm not sure what the best way to send actions from the delegate back to the view controller.
For example, the user pushes a button, the VC messages the Delegate. That part I understand. Then the delegate takes action, and following that the delegate wants to update the VC (e.g., update a label).
So what I missed (or have forgotten) is how this gets done, while maintaining separation between the UI and the model. I suppose I can use the notification center. Or I think I can just have the view controller pass a callback to the delegate. Or maybe there's another choice I don't know of. Can someone give me a recommendation, please?
I think you're slightly misunderstanding the MVC paradigm. Models should never be delegates of views, since models should have no dependencies or knowledge of any view classes. Typically, a view sends a message to its delegate or target (if you're using target/action), which is usually a controller (often a subclass of UIViewController on iOS). The controller then accesses data from the model and can update any views that need updating. I'd recommend reading the MVC fundamentals guide for a more complete explanation.
Basically you're right, you could do all the notification-related things yourself (i.e. with NotificationCenter) but since we're talking about UI-Stuff here I would greatly recommend you to use IBAction-Methods and IBOutlet-Properties in your code which you can easily connect to UI-Elements respectively their Callbacks in Interface Builder.
A very basic introduction to this topic can be found here:
iPhone SDK Interface Builder basic training
i hope that it is not too basic tough, and that I could lead you on the right track.
First of all delegate is NOT a Model.
Model is something passive that only holds the data (DB, plist, array, dictionary etc.).
While delegate is some set of functions that exist in order to react to some events.
Delegate is more likely to be a view controller in your case.
The view controller should react to user's action.
If the button tap should display some data from your model in some label then view controller should do all the work (receive user's action, take the necessary data from the model and display it on the view...).

iPhone app architecture

considering good design, is it better for each view controller to manager their own connection / networking / loading, or to centralize it in the app delegate, or a separate object?
Context:
I have a multi-tab app, each with a navigation controller, and a number of view controller below. Each view controller is doing networking loading XML and images. Currently, i have it setup that it calls to the app delegate to get the xml asynchronously, processing it, and then calling back the top view controller to display the info, and then launching a separate process of loading the images into an array, and sending callbacks for when each is loaded.
From an architectural view-point, is it better to have more networking code in each of the view controllers or calling back to the app delegate?
Ideas / opinions?
TIA.
It's going to make much more sense to have this in each View Controller, I think. The way you've got it set up now sounds a bit weird - you must either be using delegation so that the App Delegate can speak to each view controller, or you have a ton of references to your View Controllers in your app delegate which you probably don't need. I'd imagine your app delegate is cluttered, and I'm curious as to how you're handling things like if the user decides to stop looking at a particular view before the XML related to that view has been sent back to your app and parsed.
If you're worried about having code duplication in your View Controllers, you can probably mitigate that by using Categories.
In the end though I think it's probably best for domain objects to handle this, and not the View Controllers. For example, in viewWillAppear you get or create an instance of a domain object and kick off a getData method which has the view controller as a delegate. All of the requesting/parsing is done in your domain object and when it's completed, it sends your view controller a getDataDidFinish message or something like that.
When I have a situation like this I tend to create an object that handles all the networking stuff for me. That way I end up being able to write code like:
[netObj getXML:somePlace];
The main reason I like this approach is because it keeps my code base tidy and minimizes duplicated code.

Core Data best practices question for Navigation iPhone App

Using Apple's Mail application as an example; pretend it uses Core Data. When you touch an email account, it shows you all the messages in that account. So the controller did a fetch request for all the messages in that account.
Then you touch a message and drill one level deeper, now you are viewing a single message. This single message was probably passed from the message list controller, but -- you can also click the triangles in the upper right to move through all the messages in the same email account. This means the view controller for viewing a single email message also needs the exact same list of messages.
So you could cut and paste the fetch request logic from the list view, but that isn't DRY/don't-repeat-yourself.
Any suggestions for a best practice in solving this problem?
Create an object to manage your messages, then interact with that object to fetch the messages that you need for any of your view controllers.
This would also allow you to switch from CoreData without changing any of your view controller logic if you decided to at a later time.
The solution I've been using to solve this problem is to use the delegate design pattern. I.e., in an application with a rootViewController and a detailViewController, the rootViewController acts as a delegate for the detailViewController.
So, for example, when the user is viewing an email message (on the detail view), and they click a button to iterate to new a message, then the detailViewController informs the rootViewController via a delegate method that the rootViewController needs to display a new message.
This way, the detailViewController only every needs to know information about one model object (the email being displayed). While the rootViewController handles interaction that involve the rest of the objects.
To me, this is a nice division of responsibility, so this is the solution I've been using.