Okay. My app depends on having an active internet connection. When there isn't one, you may as well not be using it. Originally I was just going to present the user an alertView with options "retry connection" and "close app", but after a little research I found that Apple frown on apps closing themselves. So instead I decided to present an alertView with options "retry connection" and "wait", where the wait would take you to a relatively dull viewController, which would check for an internet connection periodically (once every 15 seconds or so). The idea of that is to bore the user into exiting the app for me with the home button, or to resume gameplay on the off chance the internet connection is re-established.
However, as you can imagine the internet access could go at any given time (when you're on any given view controller). This means that using segues is out of the question, because I would have to do a stupid amount of them, all going from every viewController to this one wait viewController.
Got any ideas? Is there a [self gotoViewControllerWithTitle:#"wait"]; command I don't know about?
I was thinking I could make all of my internet related stuff happen in one view controller I guess and just pass values to the other VCs if it came to it, but that seems very limiting/infantile.
Thank you in advanced and any help is appreciated :).
Have your app delegate detect no internet, and present your Modal "No Internet" view controller. Then when internet returns "dismissModalViewController" and hey presto, your previous view controller is underneath.
You could subclass 'UIViewController' to create your own base 'UIViewController' to have a generic method that checks the connection and on disconnect calls a modal view controller saying that the user has lost connection. And then maybe even pop to the root view controller. Then subclass that class and then every UIView Controller will now have the functionality you need. OOP FTW
On a side note, having a program that will only function with a working internet connection is a really bad idea. It's hard to keep the users hooked to an app when they'll be forced to quit the app when they lose connection.
Make your "no connection view controller" a singleton object. Then you can access this same instance using a class methods (e.g : [MyNoConnectionViewController shareInstance]).
Related
I have a Login interface, user interface, and a Main menu.
When I'm logging in, I switch on my user interface.
if I do a UIModalTransition, and if I come back to the page, I need to RE-login again, it's a problem for me.
I search a method for Switch between view but don't close them, because if you closed them, views restart, it's the same for UIWebview, I would like to switch between views without closed and reset views.
Is it possible ?
I don't really know what kind of Code is it.
If you have ideas, please tell me.
In this answer i tried to explain the view controllers orchestration as i see it.
The idea is to create the manager class taking care of elements storage and presentation. It also mentions the way to manage the login information.
You can use pushViewController ie..
[self.navigationController pushViewController:yourUserInterFaceViewController animated:YES]; for transition between login and user interface.
you can use 3 ways
1)pushing the view into UINavigationController
2)presenting the view with ModalViewController
3)adding subView to rootViewController and remove it using removeFromSuperView when needed.
(you can allocate them when app launches and access them using
[YourAppDelegate sharedApplication].yourViewController)
Since your appDelegate is a singleTon class it will always return the same viewcontroller you've allocated at the time of launching the app. You can use Lazy Load also.
May be this will help.
I have been searching the net, and i have found many very good examples on how to create a login page for your iPhone app. However... none of then meets my demands, an since i am new to iPhone development( i know java / c / C++ and objective-c), so the programming itself is not the issue.. The issue is where to put the code and what design patterns to use..
My app is a basic tabbar controller with 3 tabs that could contain navigation controllers, but that is not important.. it is the part before the tabbar controller i am interrested in, namely the need to authenticate the user towards a Lotus Domino Server. I have the authenification code working, so that is not the issue either..
By the way, i am concentrating on IOS5 and using storyboards..
Where do i put the "check if user is still authenticated" code ? The domino server will log the user out after 1 hour, so if the user has the app open(in background) then the code that downloads data will die if the user is not told that the session has expired..
So here is what i would like..
When the app launches, show the login page. This is working for now with the Login View Controller as initial controller, and a modal segue to the tabbar controller..
Next time the App is launched(either from background or from new is user has closed it completely), check if username and password is stored in userdefaults, and then just login in background, and if that fails(password has changed or another failure) then show the login view controller again..
So to sum up, where do i put the "part 2" code ? I have a seperate authenticator class that is using delegates, and i can use this class to perform the authentification, and the it will answer back if all is good.
Do i put this in the AppDelegate code ? If i put it in one of the tabbar viewcontrollers, then there might be an issue with the user having tab2 open when launching after 2 hours, and if the check is in tab1, then tab 2 will fail.. Should i put the code in ALL the tabbar viewcontrollers ? Naaa, that is ugly..
I am leaning towards the AppDelegate(appdidbecomeactive), but can that be used as delegate in my authenticator class ?
That was a bit long, sorry for that, but i needed to explain my problem fully so people would understand what i need..
Thank you for your help.. This is my first post, but this forum is fantastic :)
I'd definitely put both part one and part two code in the AppDelegate.
This allows you to create the appropriate viewcontroller at app start and remove the tabbarcontroller from within the AppDelegate if the authentication times out etc.
I'm not sure about your modal segue to a tabbarcontroller though (I'm not familiar with storyboards yet though). Modal implies you wouldn't be able to present any other view modally on top of the tabbar controller. I think it sounds like it would be much more appropriate to create your logincontroller and tabbarcontroller programmatically and add/remove them directly in your application’s main window as needed from your AppDelegate.
I would tell the AppDelegate to check the login status very time the tab is changed or data loaded.
In my app there is authentication required, so when you launch one of the tabs on tab bar, "class A" checks are there credentials saved if not, "class B" modal view controller with fields to login launches.
So my question is : in which method in class A (loadView, viewWillAppear or maybe in another one) should be implemented checking if there are credentials saved and other stuff described above.
And my additional second question is:
is pushing modalviewcontroller correct way to show login screen, or i should do that differently?
Thank you for reply guys.
OH ! One More Thinh
And one more thing. I've done implementing LoginView by adding delegate and presenting ModalVC (Harkonian the Piquant's method). But in my tab bar app i have got very confusing problem. I mean when user taps login button (assume that everything was correct and he's able to secured data) how PROPERLY switch to tab where is secured info. I mean previously selected tab.
i did it by adding in
-(IBAction) login {
//some code
self.tabBarController.selectedIndex =1;
And it seem to work good but is it correct ?
I have a very similar use case in my app -- it requires a passcode to authenticate. After a lot of testing and tweaking I found the following design to be the best approach:
Don't use class A to launch your credentials VC -- use the app delegate instead.
For security purposes, typically you'll want the credentials VC to show before the user can view the underlying view. It's much easier to handle this in the app delegate than in a VC. In addition, you need to consider what happens when your app is backgrounded -- a screen shot is taken of the current state of the app. If you are using viewController A to show the credentials view, when the app relaunches the user will be able to see whatever sensitive information was visible on app close until the app finishes launching and VC A presents the credentials VC.
Don't insert your credentials view into an existing ViewController -- use a new UIWindow instead.
You don't ever want any other view to be able to sit on top of your credentials view. Ever. Even views that would normally always be on top, like UIAlertView. The easiest way to achieve this is to have a special UIWindow just for your credentials view. Show this window and hide the primary app window whenever you need to display the credentials view.
How does this approach look in practice?
If you are at all interested in how well this design works, you can check out the passcode feature in Audiotorium Notes for iPad. I spent a lot of time with this design to make sure it was as secure as possible.
If you have any specific implementation quests feel free to ask and I'll try to answer them.
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.
My Rootviewcontroller uses NSURLConnection to get data from a server, and then, based on this data, loads a bunch (like 7) of smaller UIViewControllers that each also use their own NSURLConnection to get some more specific data from the server. But, the problem is, only the RooTViewController is recieving callbacks from:
- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
the other UIViewControllers never get callbacks...
You should really work with the assumption that only one view controller is active at the time. So if you want the other view controllers to do work, even when they are not visible on the screen, then you should move that logic into some singleton object that does all the network communication. The viewcontroller, when they appear, will simply ask this object for the data.
For the iPhone it is a really bad design to let inactive view controllers do stuff in the background. The only thing they do is manage the view that you currently see on the screen.
#St3fan is correct about good patterns for UIViewController. Many a developer has been burned thinking his UIViewController always has a non-nil view (it doesn't).... Even so, I'll discuss here what may be going wrong.
There are two likely causes: you're not setting the UIViewControllers as the delegates of their NSURLConnections, or you're not actually starting the NSURLConnections. The most likely cause of the latter is that you're using NIBs and expecting them to load at the beginning of the program, when they actually only load when needed.
As #deanWombourne notes, you can have all the NSURLConnections you want (**). Walk through your code in the debugger. Make sure you're not sending messages to nil. When "nothing happens" it almost always means you're sending messages to nil.
(**) Don't get crazy with connections on iPhone. Network connections are expensive to create (in both time and battery). If you can get all the data you need over a single connection, there are some advantages to doing so. This doesn't mean you should bend over backwards to avoid connections; just be careful of letting them get out of control.