My ViewController1 pushes ViewController2
ViewController2 *controller =
[[ViewController2 alloc] init];
[self.navigationController pushViewController:controller
animated:NO];
[controller release];
ViewController2 has UITableView ... in xib file I connected delegate with File's Owner. Also ViewController2 has Done button
- (IBAction)doneButtonPressed {
[self.navigationController popViewControllerAnimated:NO];
}
The problem is that if to click table rows and done button at the same time, sometimes didSelectRowAtIndexPath: method calls after that ViewController2 was popped, and I have SIGABRT error and this thing in logger :
[__NSCFSet tableView:didSelectRowAtIndexPath:]: unrecognized selector sent to instance 0x62579d0'
So how tableView:didSelectRowAtIndexPath can be called after I popped viewController2 ? It should be dead...
One easy fix is to do this:
- (IBAction)doneButtonPressed {
self.tableView.delegate = nil;
[self.navigationController popViewControllerAnimated:NO];
}
That way you guarantee that while you're leaving that view no more delegate calls will happen. You could also do this in the dealloc method for the view controller (probably a better place for it).
popViewController & pushViewController methods perform their tasks asynchronously. They use an animation block to slide the viewController in and out. The ViewController gets removed from its superview and gets released in the completion portion of the animation block. The crash is because of this delay (I think 0.3 seconds).
Related
I am using this code to hide a button in a different view controller, but the button does not get hidden when the button is pressed to hide the button in the other view controller.
This is the code I am using to hide the button in the other view controller:
[self dismissModalViewControllerAnimated:YES];
NSLog(#"Exited");
ViewController *vc = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
[vc.mainbutton1 setHidden:YES];
Why is this not working?
Thanks!
take a BOOL variable in ViewController controller and make the property and synthesize also.
and do this.
ViewController *vc = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
vc.check = YES;
in the view controller viewdidload
write this
if(self.check)
[mainbutton1 set hidden:YES];
The other answers should work unless...
Judging by your code I am going to guess that you are trying to hide a button on the viewController that presented the modal view?
If this is correct then what you are doing will not work as you are creating a new instance of ViewController which is not the already existing viewController you want to use.
Although the docs say that it is fine to call [self dismissModalViewControllerAnimated:YES]; from the presented modal view I tend to set up a delegate to handle the dismissal like in Apple's utitliy app template.
The reason this isn't working is because even though you have alloc'd and init'd the ViewController properly, the actual elements of that vc ViewController (including mainbutton1) have not been loaded yet.
Hitman has the right idea (and I'm voting his idea up).
Either put in a BOOL property for setting mainButton1 to hidden when the view appears, or call your [mainButton1 setHidden: YES] right after you explicitly display the view (via animation or adding subviews or whatever).
From your question it sounds like you want to hide the button in an existing view controller, whereas in your code you are creating a new one
ViewController *vc = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
[vc.mainbutton1 setHidden:YES];
Either the view controller which you observe is not the one you expect or the mainbutton1 outlet is not connected properly. You can check if the memory controller is the one you expect by logging its memory address.
NSLog(#"Hid button for view controller %p", vc);
And doing the same in the viewDidAppear callback of ViewController
NSLog(#"In viewDidAppear for view controller %p", self);
It seems you want a certain button to be hidden if something has been happening somewhere else.
You COULD, somewhat as a hack (but I don't mind that very much) control this with a variable on your AppDelegate for instance.
When the "something" is happening "somewhere else", do this:
MyAppDelegate *appDelegate = [[(MyAppDelegate *)UIApplication sharedApplication] delegate];
appDelegate.shouldHideThatOtherButtonLater = YES;
Then, when you create your new ViewController later on you could use this value to determine if your button should be visible or not like this:
ViewController *vc = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
MyAppDelegate *appDelegate = [[(MyAppDelegate *)UIApplication sharedApplication] delegate];
[vc.mainbutton1 setHidden: appDelegate.shouldHideThatOtherButtonLater ];
You will in this case have to prepare your AppDelegate for this by creating and synthesizing that shouldHideThatOtherButtonLater-property.
I have uinavigation controller with a view controller named VC1,now i have a button in VC1 that when i click on him i go to view controller VC2,this is how i bring VC2 to screen :
VC2 *tmp = [[VC2 alloc]init];
[[self navigationController] pushViewController:tmp animated:YES];
[tmp release];
now when i click in VC2 on the back button of the navigation to return to VC1 its work but i put in VC2 viewDidDisappear and viewWillDisappear methods,and when i click on the back button this function won't called, any one have any idea?
You may call the view[..] methods manually from the UINavigationControllerDelegate callbacks, however the easiest way to ensure that the methods are called by the super implementation of the UINavigationController is just to call them manually once when the UINavigationController is allocated.
See my answer here: iPhone viewWillAppear not firing
So immediately after you have called navController = [[UINavigationController alloc] init.., make sure to call
[navController viewWillAppear:NO];
[navController viewDidAppear:NO];
[navController viewWillDisappear:NO];
[navController viewDidDisappear:NO];
This should ensure events are correctly forwarded to each view controller in the future.
If you want to call the viewWillDisappear/viewDidDisappear methods, your view controller has to do that manually before popping itself off the nav stack. Have a look at this
,you might get an idea how to do it.
I have some view controller which I call with the following method:
myViewController *myView = [[myViewController alloc] initWithNibName:nil bundle:nil];
myView.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:myView animated:YES];
[myView release];
if I use the app a few times I get a memory warning and the app freezes for a few seconds! I think the reason is that i switch the view but not discharged the old one !!?!!?!!
(i set my outlets to nil and release them)
how can I unload the old view after switching to the new one?
Thanks in advance
When switching the view be sure to call dismissModalViewController:(BOOL)animated on myViewController.
In the class that launch the modalViewController you could make a property for the modal viewcontroller which you retain. Then you could write something like this.
//This would be in an action or something...
if (self.myViewControllerProperty == nil) {
self.myViewControllerProperty = [[[MyViewController alloc] initWithNibName:nil bundle:nil] autorelease];
}
[self presentModalViewController:self.myViewControllerProperty animated:YES];
Then instead of setting the
myView.modalTransitionStyle =
UIModalTransitionStyleCoverVertical;
Move that code to the modalViewController and write self.modalTransitionStyle = UIModalTransitionStyleCoverVertical; I think that looks cleaner, keep the configuration of each viewcontroller separted don't mix it up.
And as the maclema said, call dissmissModalViewController, but you probably are doing that...
Could be any number of problems but you don't need to (and can't) unload the old view. Make sure you are releasing objects and setting outlets to nil in viewDidUnload of all of your view controllers. viewDidUnload will be called when a memory warning occurs so if you don't handle it correctly you'll have leaks and can crash. Other than that, hard to know what else your app is doing that is contributing to the crash.
I'm very new to iPhone development and Objective-C. Today, I figured out how to open a new ViewController and how to return to the previous one.
Here's how I currently do this:
// In the main view controller I have a method called openSecondView that is defined like this:
- (void) openSecondView:(id)sender {
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:secondView animated:YES];
}
// In the SecondViewController I have a back button that calls a method called closeView that is defined like this:
- (void)closeView:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
My question is, how do you do properly accomplish this?
Should I call [secondView release] after calling presentModalViewController or is this done some what behind the scenes? I ask this because when I was debugging I noticed that presentModalViewController doesn't seem to be a blocking code, the next few lines of code I added seem to execute immediately, without calling dismissModalViewControllerAnimated. Are there any consequences of calling [secondView release] after presentModalViewController?
Any help/advise would be much appreciated.
Just call [secondView release] after calling presentModalViewController. The view controller will be retained until it is dismissed.
In order to speed up my app, I've create three different UIViewController in AppDelegate and it has readonly property for the controllers. Those controllers are used for navigation controller.
If I tap a button on the root view, I just show another view using pushViewController method. Let me show you some code for this here.
UIViewController* controller = delegate.anotherViewController;
[delegate.navigationController pushViewController:controller animated:YES];
At first time, this work well, but if I navigate back and tap the button again, I've got a signal 'EXC_BAD_ACCESS' at second line.
What's wrong? And, how can I prepare all of my view controllers at the beginning, not create them when they are needed?
Most of the time EXC_BAD_ACCESS means that you've released an object and you're trying to reuse it without retaining it.
Look if you have released your viewController too early and whether you are (re)using it the right way or not...
I had the same problem. My code was
AddMedia *info = [[AddMedia alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:info animated:YES];
[info release];
I was releasing my viewCOntroller which was crashing the app.
When I commented that line, It worked seamlessly. The code after the change is:
AddMedia *info = [[AddMedia alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:info animated:YES];
// [info release];