This is a two part question.
I have created a user agreement that the user must agree to when first launching the app (it is an alert with some information and agree/ do not agree button)
I call upon the method that creates this alert inside myAppDelegate.m and within the method
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
The problem is the alert pops up when the splash screen has finished loading and my first view comes up. I want this to happen during the splash screen. How would I do this?
The second question is When the users presses the "Do not agree button", I want them to exit the app so I have programmed it with
exit(0);
Is there a better way and will apple reject my app because of this?
Thanks in advance
1) You can't -- during the splash screen (your default.png) the app is loading into memory, and it cannot therefore execute any code, including presentation of a UIAlertView. That's why you don't see the alert until the splash disappears -- removal of the splash screen is the last thing that the app does before calling applicationDidFinishLoading:withOptions:.
What you can do is create a view controller that mimics your splash screen. This is easy -- you can even reuse default.png as a background if you want, though a better idea is just to present in this first view controller your agreement text and agree/disagree buttons.
As to your question re: use of exit(), it's best to avoid doing that. If the user refuses, you can simply do nothing. Of course, if you go the view controller route as I suggest, you can leave presented another opportunity for the user to agree.
Another thought is that Apple allows you to customize the EULA of your app when you upload a binary -- you could put it there and be covered.
Why not load our default.png as the background of you initial view and just handle the Alert in it's controller. you can always add another view or segue based on the answer.
The problem is the UIAlert blocks the Main thread, so it could stop your app from launching in time, and the process could be terminated.
Related
When subclassing PFLogInViewController for customization. How do I change the size of the view?
I have looked at this tutorial: https://parse.com/tutorials/login-and-signup-views
but it does not seem to have the answer.
My app is based on a UITabBarController and one of the tabs needs log in.
Nevertheless if the user cannot log in, he should still be able to use the other tabs.
In the present situation, when the user taps on the tab asking for login; he has to log in or kill the app to get out. Because the PFLogInViewController takes up all the screen and there is no way out by hitting a different tab (all covered).
This is obviously not very nice.
How can I keep the tabs at the bottom visible?
I tried to change the self.view.frame or the self.logInView.frame in the viewDidLoad method of my PFLogInViewController subclass, but it seems to have no effect at all.
Then you should make your app so that it doesn't start with the login viewcontroller, but rather opens to the parts that are available to all. Include some button or other mechanic to take the user to the login page.
You could include a button on the login page that says "Use the app anonymously" or similar, which triggers a segue to a main view. On subsequent app launches, the user is taken to this main view immediately. You would still need a way for the user to login later on.
Okay, so I'm building an universal iOS app with an initial login view (view controller named LoginVC), just a plain simple UIViewController. If the login is successful the app segues to an navigation controller (MainNavigationVC). I created this segue through the storyboard gui of XCode, so no programmatic creation of the nav controller is done. The nav controller is presented modally in fullscreen, so the rest of the app is run atop the login view, with this nav controller as the centerpiece of everything.
The navigation controller contains a view (with a view controller named UserStartPageVC), and in its navigation bar is a logout button. This button sends an target action to UserStartPageVC, with the goal of dismissing the nav controller thus bringing the user back to the login view.
So far everything works fine. I can login and use the app as intended. But! When I log out and then re-login XCode tells me this:
Warning! Attempt to present <MainNavigationVC: 0x753110> on
<LoginVC: 0x756fcf0> while a presentation is in progress!
I suppose this means that the login view is trying to modally display a MainNavigationVC navigation controller, but another one is already displayed, right? But how? Can a view be presented without showing?
And how can I get rid of the old nav controller when logging out? I've tried several ways of dismissing the modal view, for instance:
from within UserStartpageVC running
[x dismissViewControllerAnimated:YES completion:NULL]
[x dismissModalViewControllerAnimated:YES]
where x is either self, self.parentViewController or self.presentingViewController.
setting the LoginVC as a property in UserStartpageVC and running
[self.loginVC dismissViewControllerAnimated:YES completion:NULL]
and so on.
All of the tested calls actually brings me back to the login screen, so it's kind of working.
Any ideas? Relevant code samples can be provided if necessary, I just couldn't figure out which pieces that were of interest. The seguing to the navigation controller has no code (except for a performSegueWithIdentifier:sender:), and the code for dismissing it is the part I cannot seem to get straight.
As a sidenote. So far this isn't a REAL problem; the app runs, and it IS possible to logout and re-login without any other side-effects than an error message in XCode. But I suppose this will be a memory leak if users logout and login multiple times, and I'm not in the mood of an unnecessary rejection from Apple.
I discovered another way to get the exact same error message. Lucky me!
If you created a segue at one point and had it tied to a button (click button -> new view) and then later give that segue a name and invoke it directly using
[self performSegueWithIdentifier:#"identifierName" sender:self];
then you can get this error because you can effectively trigger the segue twice. I thought making the button invoke an IBAction would turn off the segue I had set up in the first place, but apparently not. Hitting the button triggered the segue twice, but after I deleted the segue and re-created it as a manual segue on the view with the same identifier then I was able to invoke it via the above code and not get the warning message.
Hoopla! My bad.
Seemed I had set up the notification observing from the login API call in a stupid way. For every time the user triggered a login (or re-login), it added itself as an observer for the notification; the result was that it performed one more segue for every time a login was done.
And doing multiple segues at the same time, is... well, obviously bad.
My iOS app sometimes displays a Greystripe fullscreen ad on startup. If this ad shows, then when I dismiss it, later I will tap a textfield in a UIWebView but the keyboard won't show up. However, if the Greystripe ad DOESN'T appear, then all is well and the keyboard will show up as expected.
After doing some research I think it has something to do with Greystripe making itself the first responder, but I'm not sure how to fix this.
Edit:
I use adwhirl and so to get the startup ad I do exactly as it says here: http://wiki.greystripe.com/index.php/AdWhirl
The UIWebView is inside another controller that is presented with presentModalViewController:animated: from the main view.
I narrowed the problem down: the problem is caused after initiating Greystripe, which occurs either from the full screen startup ad that I initiate manually or from AdWhirl automatically initiating it to display a 320x50 Greystripe banner.
After hours of debugging I finally figured it out. I use SVProgressHUD to show loading status while my UIWebView is loading. SVProgressHUD.m makes itself the key window, then when it is dismissed, it returns the key window status to the "topmost" window. For some reason Greystripe, unlike all the other ad networks I'm using, makes itself the topmost window. So the problem could be Greystripe making itself too important, or SVProgressHUD miscalculating the topmost window!
To solve this, I had to manually make my view controller which contains my UIWebView the key window every time after dismissing SVProgressHUD:
[SVProgressHUD dismiss];
[self.view.window makeKeyWindow];
I am having two controllers like
firstController and secondController
When am in firstController am clicking on home button its going to background state,
but, when am again enters to foreground i need to show secondController instead of firstController.
For that I am implementing code in forground to navigate to secondController its navigating but first its showing firstController and then its showing secondController I need to avoid that how to do am not getting.
Please anyone help me to solve this.
Thanks in Advance.
Regards,
Sai.
When your app goes to the background, iOS takes a screen shot of it's state. Therefore when you push your controller at the didEnterBackground stage, it won't make a difference at next activation whether you pushed another controller or not - the screenshot of second controller will be shown regardless.
Now, the good practice is to hide sensitive information when the app resigns active in the willResignActive app delegate. You could also try pushing your secondController when the app resigns active but then you will need to keep track of whether it ever went to the background or not and push the firstController when app becomes active again (in case it never went to the background)
Hope this explanation makes sense
i want to show a progressView when the app is launching (with the splash screen) so, in the appDelegate .h file i declared a progressView :
UIProgressView *progView;
and in the appDelegate .m file i did this :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
sleep(1);
progView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progView.progress = 0.75f;
// the rest..
}
i didn't see the progress bar in the splash screen, help please, thx in advance :)
You cannot influence the splash screen itself, it's only a static image.
What you can do however is to let your app load until you get the delegate message, then fire up some basic UI which shows your progress view and then do some heavy startup process in a background thread, updating your progress bar accordingly. When the thread has finished its work, call back to the main thread to start the real application.
Edit: Updated my answer to clarify some things
The application startup in iOS happens basically in 2 phases.
The operating system launches your application, the app sets up basic stuff, starts the run loop, etc. During this time the splash screen is shown. During this phase the application is not under the control of the programmer.
-application:didFinishLaunchingWithOptions is called. In this method you as a programmer may do some startup tasks, such as loading the database, connecting to some service, etc. During this phase you can influence the user interface and also show for example a progress bar. If you need to do this, create a background thread and do the setup work there.
Note: It does not work if you just put a progress bar on the UI and then do some stuff in the -application:didFinishLaunchingWithOptions: method, since the UI is not shown until after this method has returned. That's why you need to do the setup in a background thread.
is that all the code for progView? Cuz you haven't added it as a subview to anything, so how would you be able to see it? You need something like:
[splashView addSubview:progView];
frenetisch gave some reasonable explanation of the startup process of an IOS app, but it sounds like you need to do some basic investigation into this. It generally takes very little time before your didFinishLaunchingWithOptions is called and you can show your first view. But what things do you then need to do before your app is actually usable? You want to show a progress view so there must be SOMETHING that you plan to do that takes some time. It's while THAT is going on you need to show the progress view and somehow update it's progress.