i need help here, i'm using a custom segue to push a view controller to another view controller.
when pushed using cutom segue, the uiactivityindicator will not animate automatically when view loaded.
however if i used the push method on the storyboard, the uiactivityindicator animate automatically.
what i had done wrong ?
-(void)perform {
UIViewController *sourceVC = (UIViewController *) self.sourceViewController;
UIViewController *destinationVC = (UIViewController *) self.destinationViewController;
[UIView transitionWithView:sourceVC.navigationController.view duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[sourceVC.navigationController pushViewController:destinationVC animated:NO];
//NSLog(#"count of subview %i", [self.view.subviews count]);
}
completion:NULL];
}
Try this:
UIViewController *sourceVC = (UIViewController *) self.sourceViewController;
UIViewController *destinationVC = (UIViewController *) self.destinationViewController;
[UIView transitionFromView:sourceVC.view toView:destinationVC.view duration:.5 options:0 completion:^(BOOL finished) {
[sourceVC.navigationController pushViewController:destinationVC animated:NO];
}];
The -pushViewController:animated: should not be putted in the animation block but the completion block.
Related
I encountered this problem when doing my MCQ Game app testing.
I'm using ARC & Storyboard custom segue and [self performSegueWithIdentifier:#"VC" sender:self]; to push from ViewController1 to ViewController2 but very seldom popping back the ViewController1 due to the naturals of the app, moving forward from question to question. the app will become very very sluggish after multiple times pushing. what is the best way to solve the problem?
Custom segue:
-(void)perform {
UIViewController *sourceVC = (UIViewController *) self.sourceViewController;
UIViewController *destinationVC = (UIViewController *) self.destinationViewController;
[UIView transitionWithView:sourceVC.navigationController.view duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[sourceVC.navigationController pushViewController:destinationVC animated:NO];
}
completion:^(BOOL completed)
{
//[sourceVC.navigationController pushViewController:destinationVC animated:NO];
}
];
}
I suspect there is a strong reference cycle going on. Run Leaks to make sure that the previous view controller does not have a strong reference after you push the new one.
i changed the custom segue from push to pop, based on my view controller name, and it works :)
-(void)perform {
UIViewController *sourceVC = (UIViewController *) self.sourceViewController;
//UIViewController *destinationVC = (UIViewController *) self.destinationViewController;
NSInteger index = -1;
NSArray* arr = [[NSArray alloc] initWithArray:sourceVC.navigationController.viewControllers];
for(int i=0 ; i<[arr count] ; i++)
{
if([[arr objectAtIndex:i] isKindOfClass:NSClassFromString(#"mainViewController")])
{
index = i;
}
}
[UIView transitionWithView:sourceVC.navigationController.view duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[sourceVC.navigationController popToViewController:[arr objectAtIndex:index] animated:NO];
}
completion:^(BOOL completed)
{
//[sourceVC.navigationController pushViewController:destinationVC animated:NO];
}
];
}
My first view contains a button and after pressing a button, i will end up with the second view. what I have done is
FirstViewController.m
- (void)pushToWishList {
SecondViewController *controller = [[SecondViewController alloc] initWithNibName:#"SecondView" bundle:nil ];
[UIView beginAnimations:#"flipping view" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[self.view addSubview:controller.view];
[UIView commitAnimations];
}
SecondViewController is an UIViewController such that :
SecondViewController.h :
#interface SecondViewController :
UIViewController
SecondViewController.m
self.navigationController.navigationBarHidden = NO;
self.navigationItem.hidesBackButton = NO;
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
What is happening is the top navigation is disppearing and the UITableView in my second view can not be scrolled up and down. My program is crashed whenever I try to do this.
Please advice me on this issue. Any comments are welcomed here.
First off its easier to not addSubview: just use this code to turn your page:
- (IBAction)myCart:(id)sender; {
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
}
This will allow your tableView to scroll! Also, your method return type is void, if you are using a button to call this method, you need to change the return type to IBAction which works for buttons.
I am calling turnView method who must get dissapear menuView (current) and may display adjustView. When method is called, it is executed with no errors but it does not switch views, menuView keeps and it returns to following line of method call. How to solve it? Thanks
call from menuView:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
aboutTabController * myObject = [[aboutTabController alloc] init];
if (indexPath.section == 1) {
switch (indexPath.row) {
case 0:
[myObject turnView];
break;
case 1:
//
break;
default:
break;}
}
}
method implemented on controller, menuController was defined for menuView class:
- (void) turnView
{
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
if (self.adjustController == nil)
{
adjustView *aController = [[adjustView alloc] initWithNibName:#"adjustView" bundle:nil];
self.adjustController = aController;
[aController release];
}
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[self.menuController viewWillDisappear:YES];
[self.adjustController viewWillAppear:YES];
[self.menuController.view removeFromSuperview];
[self.view insertSubview:adjustController.view atIndex:0];
[self.menuController viewDidDisappear:YES];
[self.adjustController viewDidAppear:YES];
[UIView commitAnimations];
}
There are some major conceptual problems in your code, let me try to address them one by one:
Logic in didSelectRowAtIndexPath:
You are creating a new view controller no matter which row is being selected. You should only create it when you need it. Also you if and switch statements are very convoluted and difficult to read.
Calling delegate methods
The methods viewWillAppear: viewDidDisappear: etc. are there for you to catch these events, not to call them yourself. This might make sense in some cases, but they will have absolutely no effect in your animation block.
Animation with blocks, or using built-in animations
You should do your animation with the new block syntax. However, for just flipping to the next view, you can use an official API from Apple without having to program your own animation.
Thus,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section==1 && indexPath.row==0) {
adjustView *aController = [[adjustView alloc] initWithNibName:#"adjustView" bundle:nil];
aController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:aController animated:YES];
[aController release];
}
}
You can get rid of the controller by calling [self dismissModalViewControllerAnimated:YES] and the animation will automatically be in the other direction.
Sample on GitHub
I have a strange problem.
I have Navigation-based app with two UIViewControllers and Curl effect for transition between these.
I add to bar button and add custom action:
-(IBAction)pushPage
{
NSLog(#"push page");
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[UIView beginAnimations:#"animation" context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:NO];
[self.navigationController pushViewController:secondView animated:NO];
[UIView commitAnimations];
[secondView release];
}
In SecondView I have a button with action:
-(IBAction)back
{
[imageAnimationIssueAppDelegate backPage];
}
Method backPage in AppDelegate:
-(void)backPage
{
NSLog(#"backPage");
[UIView beginAnimations:#"animation" context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.navigationController.view cache:NO];
[self.navigationController popToRootViewControllerAnimated:NO];
[UIView commitAnimations];
}
PROBLEM:
On the RootView I have UIImageView with animation:
- (void)viewDidLoad
{
[super viewDidLoad];
animImage.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"4.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"2.png"],
nil];
animImage.animationDuration = 0.5;
animImage.animationRepeatCount = 0;
}
I start it in viewDidAppear:
- (void)viewDidAppear:(BOOL)animated
{
NSLog(#"First view - viewDidAppear");
[super viewDidAppear:animated];
[animImage startAnimating];
}
I stop it in viewDidDisapear:
- (void)viewDidDisappear:(BOOL)animated
{
NSLog(#"First view - viewDidDisappear");
[super viewDidDisappear:animated];
[animImage stopAnimating];
}
When I back from SecondView animation is stoped! But [animImage isAnimating] say YES!
It doesn't start witout update screen - you can click to button on the bottom and see it!
Is it bug?
Animation works without custom transitions.
When I set animated:YES for push or pop view, animation works with custom transitions between views.
Why?
Is there simple way to update displaying view to start animation?
I think you should have to write
[yellowBatterfly startAnimating];
in viewDidLoad method. and change method from
viewDidAppear to viewWillAppear and
viewDidDisappear to viewWillDisappear.
Hope It will works...
I think you have to perform the animations on the view using:
[UIView commitAnimations]
is there something that can call a -(void) every time a view shows.
I am rotating between two views, so when i go to the second view and then return to the first view I want a void to be called automatically from the first view
I've try to do this with -(void)viewWillAppear:(BOOL)animated and - (void)viewDidLoad
by putting a NSLog in them but it doesn't print when i return to the first view.
any suggestions?
If you are updating the first view with data from the second, use an observer on the model that is being updated. If the second view is being removed as a subview, you can observe the subviews. Alternatively, you can use a block callback closure.
In the interface:
IBAction(^doOnClose)(void);
and:
#property (nonatomic, copy) IBAction(^doOnClose)(void);
In the method that closes your second view:
if(doOnClose) doOnClose();
And finally to define it from your first view:
view2.doOnClose = ^{/*Do this when view 2 closes*/};
I have two methods in the app delegate
-(void)goTo1{
[self.window addSubview:[viewController view]];
[settingsViewController.view removeFromSuperview];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
//removing the settingsViewController form the view and setting the animation
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:window cache:NO];
[UIView commitAnimations];
[settingsViewController release];
settingsViewController = nil; }
and
-(void)goTo2{
//calling the .xib file and the SettingsViewController
SettingsViewController *aSettingsView = [[SettingsViewController alloc] initWithNibName:#"Settings" bundle:nil];
[self setSettingsViewController:aSettingsView];
[aSettingsView release];
[self.window addSubview:[settingsViewController view]];
//moving the view 30px down
[[settingsViewController view] setFrame:CGRectMake(0, 20, 320, 460)];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
//setting the animation
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:window cache:YES];
[UIView commitAnimations];
[webskiAppBetaViewController release];
webskiAppBetaViewController = nil;
}
and IBActions in the 2 view controllers
first One
-(IBAction)goToView2{
WebskiAppBetaAppDelegate *mainDelegate = (WebskiAppBetaAppDelegate *)[[UIApplication sharedApplication] delegate];
[mainDelegate goTo2];
}
and second one
-(IBAction)goToView1{
WebskiAppBetaAppDelegate *maniDelegate = (WebskiAppBetaAppDelegate *)[[UIApplication sharedApplication] delegate];
[maniDelegate goTo1];
}
so now when i call goToVIew1 I also want to run a method that is in the view 1
something like this
-(IBAction)goToView1{
WebskiAppBetaAppDelegate *maniDelegate = (WebskiAppBetaAppDelegate *)[[UIApplication sharedApplication] delegate];
[maniDelegate goTo1];
[self methodInFirstVIew]; //this method is in the first view
}