I have an app that has many web services and notifications going on. I need a logout feature. I wish there was a way simply to kill the app and restart it but there is not. Does anyone have some recommended guidelines on creating a logout function (it will take the user back to the login screen). The problem is there are notifs that should be unsubscribed from, views that should be removed, view controllers that I want to be released, then everything to reinitialize. That seems like a lot of work for a simple task. Any thoughts?
The first thing to make sure when terminating all requests is to change all delegates that are supposed to receive responses to nil. After you've taken care of this, you should indeed remove all irrelevant view controller's views from your root view (and release them if they are retained anywhere), and of course flush any existing data you don't need. If you design your MVC elegantly, you can achieve these actions without a lot of fuss, for example a ScreenManager Singleton class that manages all your view controllers should have no problem taking you back to the login screen while releasing any other view. A DataManager Singleton class that holds various data collections should have no problem removing any unneeded data entities and so on...
Related
Here's the scenario:
-A UIViewController (A) is pushed onto the navigation stack
-On viewDidLoad an async GET is called using AFNetworking (a singleton AFHTTPClient shared throughout the application) to populate various user elements on the view (say a UILabel).
-The user presses the back button before the request returns
-Assume other active view controllers may be making requests so you can't cancel all open operations
So question #1 is, should you track the open requests made by UIViewController A and cancel the outstanding ones when the user leaves that view, or should you let them finish up and ignore them? Since AFNetworking uses blocks, the user elements being updated are retained inside the block and therefore won't cause a crash when the success/fail block is executed after the view has been popped. However the downside to ignoring them seems to be unnecessary network traffic.
Question #2 is, where would you execute the code to cancel the operations made by UIViewController A? viewDidDisappear doesn't seem right because the user may have gone forward (pushed a new view onto the stack) instead of back (popped the current view), in which case you don't want to cancel the open requests because the user may come back to the current view and it won't load again. However, I don't think dealloc or viewDidUnload will be called while the request is executing since the block will keep a retain on the user elements so I don't think it can go there.
Would appreciate thoughts on this. What do you think is best practice?
Generally speaking, you don't really need to cancel requests when a user leaves a view controller. In terms of memory management, a reference to block self will prevent any crashes caused by sending messages to deallocated instances, so no worries there.
As far as user experience, I would say that you shouldn't really worry about it until it's a problem (we developers have a knack for guessing completely wrong on what will be slow in our applications). If you are making large GET requests, though, and it's creating noticeable sluggishness, my suggestion would be to have the controller do HTTPClient -cancelAllHTTPOperationsWithMethod:path: in -viewDidUnload: (any other callback would be premature).
Maybe you could have a singleton which manages all the network stuff, and just set its delegate to the current vc (in viewDidLoad) so you get any incoming data, and send it a cancel message when the vc disappears (or else let a different vc become its delegate). Or the singleton could keep the data for access by any vc at some later stage. I tend not to put async code into my VCs for this reason.
What is the need of delegation in iphone/ipad development or objective C?
I read so many articles on it. All were telling how to implement the concept, but no one was telling why we need to implement that, in which case we should implement it.
Suppose you want to implement Login functionality in your app ... now you won't show Login screen every time you run your app.. only when it is first started and you don't have a login and password...
So in this case..
Your app starts :
View 1 loads (default view )
You check no Login name is there..
You load a new view..(Login View ) .
User enter his details..you get your login and password...
now you want to go back to default view and load the main app with
the names the user entered in Login View....
Now you will use delegate to pass these information(login details) back to default View..so that it knows..its details. now there are many different ways to do these things...like notification and singleton classes.. but when you want to sent more than 3-4 sets of data.. it is best to use delegates
Think of all the components that iOS and Cocoa provide you with. TableViews, TextFields, PopOvers...etc.
When the developers wrote these components, they couldn't possibly know all the various implementations that us developers were going to create using these components. But we need somehow to communicate with them in a generic way.
These components use delegates. The delegate is an implementation independent way of describing some behaviour that your component can conform to.
When UITableView need to find out what is the height of the rows, the UITableView only needs to know about UITableViewDelegate. It doesn't need to know about MyTableViewController, JohnsTableViewController, BobsTableViewController... etc.
So the delegate is decoupling the component from the implementation and the type.
Decoupling is a good thing. It makes maintaing and changing code a lot easier, and makes code reusable.
Delegation is a simple and powerful pattern in which one object in a
program acts on behalf of, or in coordination with, another object.
The delegating object keeps a reference to the other object—the
delegate—and at the appropriate time sends a message to it. The
message informs the delegate of an event that the delegating object is
about to handle or has just handled. The delegate may respond to the
message by updating the appearance or state of itself or other objects
in the application, and in some cases it can return a value that
affects how an impending event is handled. The main value of
delegation is that it allows you to easily customize the behavior of
several objects in one central object.
SOURCE
Use a delegate if you want to talk to only one object. For example, a
tableView has a delegate - only one object should be responsible for
dealing with it.
Use notifications if you want to tell everyone that something has
happened. For example in low memory situations a notification is sent
telling your app that there has been a memory warning. Because lots of
objects in your app might want to lower their memory usage it's a
notification.
this was an answer posted to my question here
There are two key benefits of delegation: customizing objects without subclassing, and improving encapsulation.
Customization without subclassing is a benefit you get from many of the Cocoa and Cocoa-Touch APIs using the delegate pattern. If they didn't do so, you might have to subclass a UITableView every time you wanted to change its behavior by using different types of cells or a different data source. Instead, you just set the table view's delegate and data source to customize its behavior.
As for encapsulation, the delegate pattern helps you keep the different components of your code separate. For example, if your custom View needs to have some data, it would be bad practice to simply give it access to your Model, or even full access to your Controller. Instead, you'd probably set up some kind of delegate protocol for your View that your Controller would implement. That way your classes know no more about each other than they need to, so that changes in one part would be less likely to break others.
I'm designing quite a large App and on startup it will create sessions with a few different servers. As they are creating a session which is used across all parts of the app its something I thought would be best in App Delegate.
But the problem is I need the session progress to be represented on the screen. I plan to have a UIToolBar at the bottom of the main menu which I don't want to cover with the progress bar but cover the UIView above it.So the way I see it I could do it a few different ways.
1) Have the App Delegate establish the sessions and report the progress to the main menu class so it can represent it in the progress bar (will I have any issues doing this if the sessions are created in a separate thread?),
2) have the App delegate display the main menu (UIView with a bunch of buttons and UIToolBar) and have it track and display the progress (I have never displayed anything in the App Delegate but assume you can do this but its not recommended) or
3) have the App Delegate just push the main menu and have the mainMenu class create the sessions and display the progress bar.
4) I think the other way to do it is to create the sessions in a delegate class and have the delegate set to mainMenu rather than self (AppDelegate), although I've never used anything other then self so not sure if this will work or if I will be able to close the thread (through calling super maybe?) as its running in the AppDelegate rather than the delegate of the class.
As I've kinda said before the sessions are being created in a class in a separate thread so it wont lock the UI and I think the best way is the first but am I going to have issues having it running in a separate thread, reporting back to the app delegate and then sending that message to the mainMenu view?
I hope that all makes sense, let me know if you need any further clarification. Any information is appreciated
Cheers,
Presumably the state of the connections will impact on your app's functionality. I would probably think in terms of a connections manager object which is able to initiate connections, maintain their state and respond when queried about their status. In the same way as a singleton object will return the existing object or create and return a new object of none exists, a connections manager doesn't even need a "make connection" method, just "get handle" - if the connection is not open it can try to make it so.
You also mention status must be reported on the main screen. Having a manager object that is able to do tasks of indeterminate time (opening a connection to a host that may be ready, busy, far away or just plain broken) in the background and then report progress to the main thread so the UI can be updated (remember, no UIKit access in secondary threads) seems ideal and it keeps your View distinct also.
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.
I'm having problems with my application receiving low memory warnings while the user is deep within a navigation controller stack of views. After the user browses through a bunch of hierarchical options in subsequent UITableViews, he can open a PDF document in a UIWebView (in a different view controller).
Everything works fine, the PDF loads and the user can flip through the pages. However, when the document is a bit large, or has several pages, and the user taps on the "Back" button in the navigation controller, he app crashes as the previous view controller in the navigation controller stack has been deallocated.
After searching around for ways to deal with low memory warnings, and dealing with this type of problem, I found several posts that just advise people to release the objects that can be released, and then lazy-load them later on when the user tries to load a view that has been deallocated. One of these posts is Craig Hockenberry's Dealing with memory loss: the cleanup post.
While that's a bit helpful, it doesn't give me much information to work from.
Can someone provide a simple guide on how to deal with low memory warnings, and how to implement "lazy loading" of objects?
When memory is low, the system sends out a series of memory-related messages. Any instantiated view controllers will get the -didReceiveMemoryWarning message. If you don't implement this, the default action (assuming the view controller is not front-most) is to release the controller's view member. If you've got hooks into it, or perhaps into its subviews, that could cause issues when your controller gets returned to the top of the stack.
Your first task is to figure out what exactly is causing the problem. Which object is being deallocated? Usually, fixing this is simply a matter of making sure the object is retained properly.
I suggest you use NSZombiesEnabled to try and track down the object you're having trouble with. Once you have that, you can make sure you're retaining it properly.