i have a problem with switch view between 2 views with nib files !
here my code .
my first page goes to page 2 ! but at page 2 i cant back to first page ! my app go out .. here is my code :
from page 1 to 2 :
#import "HafezViewController.h"
#import "GhazaliateHafez.h"
-(IBAction)gh:(id)sender {
HafezViewController *ghPage = [[HafezViewController alloc] initWithNibName: #"GhazaliateHafez" bundle:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.3];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[self.view addSubview:ghPage.view];
[UIView commitAnimations];
}
^^^^^^^^^
this code works great !
but from page 2 to back :
#import "GhazaliateHafez.h"
#import "HafezViewController.h"
#implementation GhazaliateHafez
-(IBAction)ghtoIndex:(id)sender {
HafezViewController *back1 = [[HafezViewController alloc] initWithNibName:#"index" bundle:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
[self.view addSubview:back1.view];
[UIView commitAnimations];
}
after i tap the back button my app go to crashing ...
whats my problem ?
thank you
You are adding view2 to view1, and then adding a view1 back to view2. When done with View2, simple call self.view.removeFromSuperview and view 1 will be shown again.
Actually, looking at this again, it seems like you might want to look at presentModalViewController to show view 2.
Two thoughts that might help you on the way:
I think you might want to run this through Instruments. Are you leaking memory? You're alloc'ing a view each click, then caching it... are you releasing them?
Would it be easier to have two views that exist separate from this, in an array for example, then index the one you want to make active and wrap that into the animation loop above while releasing and hiding the other one? Not quite sure how to make the other view go away on command as release is garbage controlled... but I know there is a way to do it.
And this is from a post from earlier that helped me when I was asking how to remove a subview immediately:
myGroovySubview.hidden = YES; hides the view. You could also try to remove it from its superview with [myGroovySubview removeFromSuperview];
If you removed it from its superview, the release call should automatically remove it from memory since the reference count should be zero after that call.
Related
I've just started objective C and I'm enhancing a current iPhone app. Previous codes were done by someone else. I'm trying to switch views back - and add a page curl animation in, but when I try to go back (removefromsuperview) my screen just goes white. I understand that I'm referring to the wrong view but I have no idea how to refer it to the right one.
-(IBAction)switchBack{
[UIView beginAnimations:#"flipview" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView: self.view.superview cache:YES];
//[self.navigationController popToRootViewControllerAnimated:YES];
[self.view removeFromSuperview];
[UIView commitAnimations];
}
The commented out popToRootViewController allows me to go back to the previous page. Any help would be really appreciated. I'm going crazy with all this views >< Thanks!
Try something like this:
[UIView transitionWithView:self.navigationController.view duration:1.0 options:UIViewAnimationOptionTransitionCurlDown
animations:^{
[self.navigationController popToRootViewControllerAnimated:NO];
}
completion:NULL];
that happened because you're trying to remove the view from its superview, which is not the way it is added before, don't use removeFromSuperView if you didn't use addSubview when showing the view it self.
you should add this code to the parent which calls your current view
viewNotLoggedHome.modalTransitionStyle =
UIModalTransitionStylePartialCurl;
this way you've stated a "partial curl" transition animation for the view u're pushing
and just delete all your animation block on switchBack function so it only consist of
-(IBAction)switchBack
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
Instead of usign self.view which is a reference to your superview, you need to use the name of the view you want to use.
f.e. :
- If you have view1 and view2
- you can delete view1 by using
[view1 removeFromSuperview];
OKay I have been working on this problem for a while now, And It is well beyond my expertise thus why I am asking for help again.
I am trying to animate the transition for a tabbarbutton click to another view. I have declared in both viewController (ViewWillAppear) methods the code below
- (void)viewWillAppear:(BOOL)animated
{
//TODO: Fix transition animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight
forView:self.view cache:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView commitAnimations];
[super viewWillAppear:animated];
}
FirstViewController to the right and SecondViewController to the left.
Now the problem is happening when the user loads the app for the first time, once everything loads up and the user clicks on the tabbarbutton to go to the second view, it dose not flip.. but when you go back to the FirstView it animates then if you go to the second again it will animate this time round.. Dose anyone have any idea why this is happeneing? if you do your help would be greatly appreciated!
UPDATE::
I am trying to add a animation into viewDidLoad, however there is already an animation for an opening sequence I am loading straight away.
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//-- Start Opening Animation ------->
CGRect vaultTopFrame = vaultTop.frame;
vaultTopFrame.origin.y = -vaultTopFrame.size.height;
CGRect vaultBottomFrame = vaultBottom.frame;
vaultBottomFrame.origin.y = self.view.bounds.size.height;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.5];
[UIView setAnimationDelay:2.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
vaultTop.frame = vaultTopFrame;
vaultBottom.frame = vaultBottomFrame;
[self.view bringSubviewToFront:vaultTop]; //this should place this subview above any others on the same page
[self.view bringSubviewToFront:vaultBottom]; //this should place this subview above any others on the same page
[UIView commitAnimations];
I think this might be messing things up for me what do you think?
You do not have animation when the app loads up. Set animation in viewDidLoad for animation when the view loads up and viewDidAppear will give you animations when the user makes transition after wards (every time the tab is clicked).
This may or may not be the problem, but you should call
[super viewWillAppear:animated];
at the beginning of the method, before your animation code.
I did some digging around about this, but nothing really seems to answer my particular question (not even this: Is it possbile to removeFromSuperview with Animation?).
Basically, my app starts with a welcome screen, where a user clicks on "sign in", then goes to the sign in view, then getting to a tab bar view, which is the actual app.
The way I did it, is that I wrote a custom class - TabBarController, which sets up all the tabs and their respective view controllers. Now, when the user clicks on "sign in" i am calling removeFromSuperview and present the tabbar.
I am trying to find a way to animate the transition from the sign in page to the tab bar. I tried some proposed solutions around here, but none seems to do the job. Here is my code in the signin.m view controller. I am looking to animate out the current view (ideally, not just by fading out, but more cool stuff like flips, etc.).
//when done signing in --> go to the tab bar view
-(IBAction)done:(id)sender {
TabBarController *tabController = [[TabBarController alloc] init];
[UIView beginAnimations:#"removeWithEffect" context:nil];
[UIView setAnimationDuration:4.0];
self.parentViewController.view.frame = CGRectMake(0,0,320,480);
self.parentViewController.view.alpha = 1.0f;
[UIView commitAnimations];
[self.parentViewController.view performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:2.5f];
[self presentModalViewController:tabController animated:YES];
}
Appreciate any help!
That can't work that way. presentModalViewController dislpays the view of a viewController over the own view. It won't replace the source viewController (self).
Since you remove self.parentViewController.view from the view hierarchy, it can't present your tabController modally because you have removed self.
Anyway, i would recommend you another way to achieve your view layout:
Create a tabBarViewController and add its view to a rootView (self.window in the app delegate or whatever you are using now). Then add your login-view to the same view. Due the view hierarchy, the login-view will be displayed above the tabBar.view. And the done button should be implemented this way: (i'm using block syntax for animation as it should be)
-(IBAction)done:(id)sender {
[UIView animateWithDuration:1.0
animations:^{
self.view.frame = CGRectMake(0, 480, 320, 480);
self.view.alpha = 0.0
}
completion:^(BOOL finished){
[self.view removeFromSuperView];
}
];
}
You can animate more things than just the alpha, size or position. Just take a look about animations in the documentation. I guess, you'll be interested in view.transform to commit flip animations. ;)
This is how you have to remove the view after animating it.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelay:2.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:myView];
[UIView setAnimationDidStopSelector:#selector(removeFromSuperview)];
[UIView commitAnimations];
Hope this helps.
Happy coding.
Is it possible (at all) to load a XIB with custom AnimationTransition?
What I have done, is creating an animation that "Covers" the screen, and what I want is that after that animation has done playing, I would like it to display the new XIB.
I cant seem to find any proper solution to this...Any ideas?
To be more clear: Press a button --> Play Animation (cover screen) --> Load XIB.
Hello again! Yes, the last way you described is the way I am doing it. I have two UIViews (Might be wrong already there), that are placed off-bounds on each side, (like x.-160.y.0 and x.320y.0)
-(IBAction) leftDoor{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
closeDoor1.center = CGPointMake( closeDoor1.center.x +160, closeDoor1.center.y);
[UIView commitAnimations];
}
-(IBAction) rightDoor{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
closeDoor2.center = CGPointMake( closeDoor2.center.x -160, closeDoor2.center.y);
[UIView commitAnimations];
}
So, what I am going to do is not to "split" the current view and then open a new XIB, the effect I am searching for is a "closing door" effect, thats why I used UIView ( thought I place graphics on top of those, like two ImageViews). Then, for loading the new XIB...This is where im really puzzled. My first way of trying this out was to make three IBActions, including the two I mentioned above, and then apply all three (multiple actions) to a button. So for switching views I did something like this: `-(IBAction) newViewDisplay:(id)sender{
theView *newViewController = [[theView alloc]
initWithNibName:#"theView" bundle:nil];
[self.view addSubview:newViewController.view];
}
`
As you said, this might be over my head, but if I just got some directions, I´ll walk miles to make this work. It would really give my app a facelift. A huge thanks for taking time to answer my question, All the best/Andy
What are you covering the screen with?
Think of it this way, (it sounds like) you have 2 views, the old one and the new one that is stored in this xib. The animation is secondary.
You need to load the new view, then display it (can be off-screen), then animate it (move it) into the place you want it to go. If you want to split it into two parts, one at the bottom and one at the top of the screen, then meet in the middle, I think that's both complicated and above you skill level. (Not trying to be mean here).
If you are trying to do a split animation as described, it can be done, but you need to 'fake it'. It would involve taking a 'screenshot' (of sorts), splitting it, moving these two images so they meet with an animation, loading the view underneath, and then removing the images. Tricky stuff.
Do you have to have this sort of animation?
If you could post the code you have, I can rearrange it, and add to it, for you.
You'll need to clarify what it is exactly you want to do, though.
UPDATE 3: I added another option for autoreverse.
//You can add both doors into one animation block.
//Create an animation block. Ease Out is better for this animation but you can change it.
[UIView animateWithDuration:1.0 delay:0.0 options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAutoreverse) animations:^{
closeDoor1.center = CGPointMake( closeDoor1.center.x +160, closeDoor1.center.y);
closeDoor2.center = CGPointMake( closeDoor2.center.x -160, closeDoor2.center.y);
}completion:^(BOOL finished){
if (finished) {
//When finished, create the VC if it doesn't exist, and insert it below the 'closed door'.
if (newViewController == nil) {
UIViewController *newViewController = [[UIViewController alloc] initWithNibName:#"theView" bundle:nil];
}
[self.view insertSubview:newViewController.view belowSubview: closeDoor2];;
[self.closeDoor1 removeFromSuperview];
[self.closeDoor2 removeFromSuperview];
}
}];
I have a method like the following:
- (void)add:(id)sender {
MyAddViewController *controller = nil;
controller = [[MyAddViewController alloc] initWithAddType:1];
//controller.delegate = self;
// Do some animation. Slide it in from the right side of the screen.
CGPoint initialCenter = self.view.center;
controller.view.center =
CGPointMake(initialCenter.x + 320, initialCenter.y);
// Add the subview now with it's center + 320 off the screen.
[self.view addSubview:controller.view];
[UIView beginAnimations:#"animation" context:NULL];
[UIView setAnimationDuration:0.35];
[UIView setAnimationDelegate:self];
controller.view.center = CGPointMake(initialCenter.x, initialCenter.y);
//[UIView setAnimationDidStopSelector:#selector(aMethodToBeCalledAfterAnimationEnd:finished:context:)];
[UIView commitAnimations];
//[controller release];
}
You see I have a controller release as the last line in my add method. If I uncomment this line the animation completely dies and it just dumps the view into place with no animation.
Is there a better way to do release without having to create another method which does cleanup via [UIView setAnimationDidStopSelect:#selector(aMethodToBeCalledAfterAnmiationEnd... ?
Or can I do something like setAnimationDidStopSelector:#selector([controller release]) ? :)
Thanks in advance!
Using setAnimationDidStopSelector: is the proper way to solve the generic problem of releasing resources after an animation completes.
Take a step back and reconsider what you're doing here, though. Why are you looking to free the controller you just created? If you are only creating the controller for the purpose of getting at the view, that isn't the right way to do it. Build yourself a factory method to create your view, or use the methods in NSBundle to load the view from a NIB.
You can do this:
[UIView setAnimationDelegate: controller];
[UIView setAnimationDidStopSelector:#selector(release)];
I see you tagged this iphone-sdk-4.0. You could use the new block-based animations to do this and any other cleanup. See the documentation for details.