Changing view from one xib to another xib with animation after some times - iphone

I have made a view based application which is loading a default view ...
My default view is a splash screen ..
What I want to achieve is once default view (splash view) finished loading, after few seconds it loads another view which is either a privacy policy or application screen.
Code in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
No Change as usual ...
Above code load a view from splashscreen.xib file
Following code is in splashscreen.m
- (IBAction)loadPrivacyScreen {
NSLog(#"Switching To Another View");
PrivacyPolicyView *modal = [[PrivacyPolicyView alloc]initWithNibName:nil bundle:nil];
modal.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:modal animated:YES];
[modal release];
}
- (void)viewDidLoad {
[super viewDidLoad];
sleep(3);
[self loadPrivacyScreen];
// Do any additional setup after loading the view from its nib.
}
After three second it does get in to the loadPrivacyScreen funciton but doesn't load the view.
- (IBAction)loadPrivacyScreen;
I have created a method as IBAction because I want to hook that method with a button on privacy screen to check that function works ...
And surprisingly it works when you click the button. But it doest work on time.
Can anyone suggest me what am I doing wrong ?? or any other alternative to achieve same thing??
Note: I have also try changing
- (IBAction)loadPrivacyScreen;
to
- (void)loadPrivacyScreen;
But still same result. It is not switching ....

First of all iOS provides a simple way to load a splash screen.
Just add a Image with 320x480 resolution in the name called default.png and add that to your project it will automatically use this image as splash screen image.
In your way call the loadPrivacy screen with a timer.
- (void)viewDidLoad {
[super viewDidLoad];
NSTimer *theTimer = [NSTimer scheduledTimerWithTimeInterval:3.00 target:self selector:#selector(loadPrivacyScreen) userInfo:nil repeats:NO];
}

- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
[viewController showSplash];
}
And in the view controller, define a method like
> IBOutlet UIView *modelView;
- (void)showSplash;
- (void)hideSplash;
-(void)showSplash {
UIViewController *modalViewController = [[UIViewController alloc] init];
modalViewController.view = modelView;
[self presentModalViewController:modalViewController animated:NO];
[self performSelector:#selector(hideSplash) withObject:nil afterDelay:2.0];
}
//hide splash screen
- (void)hideSplash {
[[self modalViewController] dismissModalViewControllerAnimated:YES];
}

Related

Can I do something while splash is being showed?

Please tell me can I use a time while application is loading (while splash screen is being showed) to perform some background operations? (I need to call CLLocationManager and update current location) If I'm allowed to do it please tell me where to put a code.
It is not possible to perform anything while real splash screen is shown.
Your actions starts in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
method which is executed when splash screen removed.
If you want to perform some time-cost operation before showing user interface, your only options is show manually "fake" splash screen during this time. It can be image or anything else e.g. activity indicator or animation. If you use same image that used for splash screen,
user will see no difference, it will look like splash screen will remain some seconds longer for him, but you will already have your data loaded.
In this case your app delegate may be like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc]
initWithNibName:#"FakeSplashViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self performSelectorInBackground: #selector(someLongOperation) withObject: nil];
[self.window makeKeyAndVisible];
return YES;
}
- (void) someLongOperation{
//doing something
//...
[self performSelectorOnMainThread:#selector(atLastLoadGUI) withObject:nil waitUntilDone:NO];
}
- (void) atLastLoadGUI{
// start GUI
}

presenting modal view from app delegate unbalanced calls to begin/end appearance

This is the code I'm using to present a modal view when the app first starts
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
Security *security = [[Security alloc] initWithNibName:#"Security" bundle:nil];
[self.tabBarController.selectedViewController presentModalViewController:security animated:YES];
[security release];
return YES;
}
This is what the log says
Unbalanced calls to begin/end appearance transitions for <UITabBarController: 0x171320>.
Is there a better way to achieve this?
Also I have this method in my app delegate
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if (viewController == [tabBarController.viewControllers objectAtIndex:2]) {
//The Log Out tab locks the app by presenting a modalviewcontroller that can't be dismissed unless there is a password.
Security *security = [[Security alloc] initWithNibName:#"Security" bundle:nil];
[self.tabBarController presentModalViewController:security animated:YES];
[security release];
return NO;
} else {
return YES;
}
}
Basically one of the options on my tabbarcontroller is a logout button. The above code works fine and doesn't throw a warning to the log.
Why are you presenting it from your tab bar controller? Assuming your above code is from a UIViewController, try
[self presentModalViewController:security animated:YES];
or
[self.navigationController presentModalViewController:security animated:YES];

UINavigationController loading view incorrectly due to Orientation/Shake

Background: App has a shake to go home feature. Home view Only supports portrait.
If you shake a bit harder than usual, the view that you are on starts to rotate (which is fine) , but then it detects a shake and does a popViewControlller to the home view. When it does this it loads the navigation controller just fine, but the view under (the home content) gets loaded behind the bar and is stretched up (it's basically loading underneath the navigation bar, so it gets stretched up)
The back button handles this just fine from landscape to portrait (since its not mid transitions)
How should I go about handling this orientation change (from the shake) so I can pop back into the root view controller, without the view loading under the navigation bar?
Edit:What's happening is the content thinks that it has the entire view to load, so it stretches itself to take the entire screen, not realizing theres a navigationbar above it. I can tell since the images loading are stretched out
added a bounty of 50.
Edit Here's How I'm detecting Shakes and Popping
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if ( event.subtype == UIEventSubtypeMotionShake )
{
UINavigationController *navController = self.navigationController;
[[self retain] autorelease];
HomeViewController *home = [[HomeViewController alloc]init];
[navController popViewControllerAnimated:YES];
home.title =#"Home View Controller";
[home release];
}
if ( [super respondsToSelector:#selector(motionEnded:withEvent:)] )
[super motionEnded:motion withEvent:event];
}
Here's my App Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
navController = [[UINavigationController alloc]init];
[self.window addSubview:navController.view];
HomeViewController *home = [[HomeViewController alloc]init];
[[self home] setFrame:[[UIScreen mainScreen] applicationFrame]];
I'll include a mockup here.
Normal View:
Stretched View After a Shake/Pop:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
I'm a bit puzzled by your code so I'd really suggest starting from the beginning. As Lukya mentioned, there's no reason to recreate the HomeViewController. I'm also baffled by the "[[self retain] autorelease];" bit. That shouldn't be necessary unless you're doing something incorrectly elsewhere.
So I would start with this... In application:didFinishLaunchingWithOptions: do something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
HomeViewController *home = [[[HomeViewController alloc] init] autorelease];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:home] autorelease];
[self.window addSubview:navController.view];
}
The window will retain a your nav controller and the nav controller will retain your HomeViewController.
Then in motionEnded:withEvent: do something like:
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (event.subtype == UIEventSubtypeMotionShake)
{
[self.navigationController popViewControllerAnimated:YES];
}
}
That should be it.
If that does not work then can you give any other info? For example, does HomeViewController implement (and return YES) in shouldAutorotateToInterfaceOrientation:? If so, can you return no so it doesn't rotate since your first line says "Home view Only supports portrait"?
Edit: An example of willRotateToInterfaceOrientation:duration: and didRotateFromInterfaceOrientation: as well.
In the header for whatever controller you're detecting shakes in add a boolean:
BOOL isRotating;
In your implementation file add the two UIViewController methods we want to override -- something like:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
isRotating = YES;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
isRotating = NO;
}
Now, do something like this for your event handler:
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (event.subtype == UIEventSubtypeMotionShake && !isRotating)
{
[self.navigationController popViewControllerAnimated:YES];
}
}
in your home view controller's xib, go to the inspector for the view and set top bar as navigation bar.. and in view did load set self.navigationBarHidden = NO;...
NOTE:
there are many thing wrong with the code you've posted.. but none of them causes the orientation problem... in fact this seems to be the only code you need in that method:
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (event.subtype == UIEventSubtypeMotionShake)
{
[navController popViewControllerAnimated:YES];
}
}
so you might want to change this code as well..
Have you tried calling [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated:YES]; in your home view controller? You could also try to place this in where you detect a shake.
I have come across this issue with underlapping the navigation bar. I am not sure what causes it but you can work around it by calling,
[[self loadingView] setFrame:[[UIScreen mainScreen] applicationFrame]];
after the problem view is added to window in the application delegate.

Why can't I launch this modal view from didFinishLaunchingWithOptions?

I am trying to do something pretty easy, in my estimation:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
prefs = [NSUserDefaults standardUserDefaults];
BOOL IsLoggedIn = [prefs boolForKey:#"IsLoggedIn"];
if(IsLoggedIn == NO)
{
//Show login controller
LoginViewController *lvc = [[LoginViewController alloc] initWithNibName:nil bundle:nil];
[self.tabBarController presentModalViewController:lvc animated:NO];
[lvc release];
}
else if(IsLoggedIn == YES)
{
//Continue doing crap
}
// Override point for customization after application launch.
// Add the tab bar controller's current view as a subview of the window
self.window.rootViewController = self.tabBarController;
NSArray *tabs = self.tabBarController.viewControllers;
UIViewController *tbInvoice = [tabs objectAtIndex:0];
tbInvoice.tabBarItem.image = [UIImage imageNamed:#"Open-Mail.png"];
UIViewController *tbClient = [tabs objectAtIndex:1];
tbClient.tabBarItem.image = [UIImage imageNamed:#"Breifcase.png"];
[self.window makeKeyAndVisible];
return YES;
}
When using the debugger, I see it enter if(IsLoggedIn == NO) and run the LoginViewController code, but the view never shows.
It's driving me crazy.
I tried running the code after [self.windoow makeKeyAndVisible], but it didn't change anything.
This code looks like every example I've seen. Can anyone see what I'm doing wrong?
Thanks in advance,
Clif
I came up with this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//...
if(!loggedIn)
{
// Launch the app with login controller as the rootController
self.window.rootViewController = loginController;
// ...but switch to the original controller as soon as the UI is presented
dispatch_async(dispatch_get_main_queue(), ^{
self.window.rootViewController = originalRootController;
// ...and silently present the login controller again with no noticeable changes
[originalRootController presentViewController:loginController
animated:NO
completion:NULL];
});
}
Hpoe this post will give you some idea.

App delegate and View Controller in iOS4

With multi-tasking in iOS4, the home button puts the app into background and when it comes back into foreground I want the View Controller to 'refresh' (and hence viewWillAppear to be called). I put this in the app delegate thought this should work but nothing happens
- (void)applicationDidFinishLaunching:(UIApplication *)application {
//
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[viewController.view reloadInputViews];
}
Can anyone help me with forcing a view controller to 'execute'/refresh when it is already showing?
You could call viewWillAppear explicitly e.g.
- (void)applicationWillEnterForeground:(UIApplication *)application {
[viewController.view reloadInputViews];
[viewController viewWillAppear];
}