viewDidAppear not firing - cocoa-touch

I know this has been asked but I've tried all the solutions to no avail.
One of the tabs of my application is Logs
When it is selected a log viewcontroller with a list of logs is displayed
I have a "+" on the top menu bar to add new logs
When I select it I push the add log view controller on the stack
I add a new log - I then take the back button
when I return to the table the list is not updated
I wanted to reload the data in the table upon returning to the first view controller but
neither viewDidLoad, viewDidAppear or viewWillAppear are fired upon returning to the table
Since the first screen is oblivious
I added these to the second screen in an attempt to find any action occurring when the back button
-(void)viewWillDisappear{
NSLog(#" whered it go");
}
-(void)viewDidDisAppear
{
NSLog(#" disapeeeeeearing");
}
- (void)backAction {
NSLog(#" WHAT ABOTU THIS ");
[self.navigationController popViewControllerAnimated:YES];
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
[viewController viewWillAppear:animated];
NSLog(#"is ANY of this Happening");
}
NONE of these fire when the add screen disappears no NSLog printed
From what I've read the lack of response on the first screen is because the log table never really left the stack .
This didn't happen when I did this on another tab (different part of the app)
Whats different about this tab is the add log view controller has 5 subviews and can call modals (though it fails even when I don't call them) - I'm guessing it has something to do with that.
The call from the logs to the add logs
AddViewController *controller =[[AddViewController alloc] initWithNibName:#"AddViewController" bundle:nil];
controller.passString= newText;
[self.navigationController pushViewController:controller animated:YES];
Don't have any code for the return it just clicking on the back button at the top of the screen.
sorry for any misspellings

That's because you aren't using the correct methods.
-(void)viewWillDisappear{
NSLog(#" whered it go");
}
and
-(void)viewDidDisAppear
{
NSLog(#" disapeeeeeearing");
}
Aren't declared anywhere. I believe what you meant to write was:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSLog(#"About to disappear");
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
NSLog(#"Did disappear");
}
Methods are case sensitive, and you can't just leave out arguments and expect it to work.

Related

How to handle users pressing back button too quickly after pushing a viewController?

Usually after the viewController is pushed, I want to do certain things. In add phone feature, for example, I would open edit business and set the focus to the phone field.
If after viewController is pushed users press back button too quickly the app crash.
What's the standard way to do so?
This is the code:
+(BGBusinessEditViewController *) pushNewEditViewControllerWithBizandReturnValue: (Business *)biz withNavController :(UINavigationController *) nav andSelectPhone:(BOOL) selectPhoneAfterward
{
BGBusinessEditViewController * editBusiness = [[BGBusinessEditViewController alloc]init];
//[editBusiness view];//load the stuff first
[nav vPushViewController:editBusiness animated:YES andPerformBlock:^{
if (biz) {
editBusiness.biz=biz; //viewDidload must be called first before setting bizs
}
if (selectPhoneAfterward)
{
[editBusiness selectPhone];
}
}];
return editBusiness;
}
-(void) selectPhone
{
NSIndexPath * ipth =[NSIndexPath indexPathForItem:BGBusinessEditTextPhoneNumber inSection:0];
[self.tableView selectRowAtIndexPath: ipth animated:NO scrollPosition:UITableViewScrollPositionTop];
[self tableView:self.tableView didSelectRowAtIndexPath:ipth];
}
Basically I created a category in nav View Controller that will run code only when the navigation controller already reach - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
Well, Hide the back button until viewDidAppear, and then unhide it.

Changing navigationController.delegate causes to bad access

This may sound a newbie question, however I'm new t iOS dev.
I've a view pushed in navigationController, let say it is the 3rd pushed view.
In that view I set self.navigationController.delegate = self;. I've changed delegate because I need to handle case when user goes to previous view i.e. pops from current view.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([[viewController class] isEqual:[MainViewController class]]) {
...
}
}
It works OK, but when I pop the current view and press navigation back button again (i.e. switching to first pushed view) I'm getting bad access error.
So what I'm missing ?
What is the correct way to handle navigation back button press ?
It's because navigation controller sends a message to popped and deallocated view controller, you have to set the delegate each time you do the popping and pushing. Also add self.navigationController.delegate = nil; to dealloc method of your viewController.
Place below in the Viewcontroller in which you assigning self.navigationController.delegate = self
-(void) viewWillDisappear:(BOOL) animated
{
[super viewWillDisappear:animated];
if ([self isMovingFromParentViewController])
{
if (self.navigationController.delegate == self)
{
self.navigationController.delegate = nil;
}
}
}

viewDidLoad issue

I am having problem with ViewDidLoad Method.I have one .Xib File in my app and 5 viewControlelr.And Each View Controller Contains some initialization and method calls.
Problem is at the startup all the ViewDidLoad method runs.
Is there any way i can do this just when my ViewController will be called and the View is Loaded on the screen?
What is the proper way in this case?
I tried like this code :
-(void)viewDidAppear
{
[ScoreWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://smwebtech.com/Pandit/web_service/getScore.php?u=aa"]]];
}
But my program is not reaching this method.Why?Am i missing something?Please take a look.
Use viewWillAppear method instead. It is only called when the view is going to appear on screen.
Or viewDidAppear which is only called after the view appears on screen.
EDIT:
Both viewWillAppear and viewDidAppear take a BOOL argument each:
- (void)viewWillAppear:(BOOL)animated {
}
- (void)viewDidAppear:(BOOL)animated {
}
EDIT2:
These two delegate methods have their corresponding 'opposite' methods that you can override to release resources you allocate in the former methods:
- (void)viewWillDisappear:(BOOL)animated {
[resource release];
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[resource release];
[super viewDidDisappear:animated];
}

Remove all settings from viewcontroller when dismissed

I got multiple viewcontrollers in my project. The first viewcontroller is called when the application starts and it presents a login screen. When the credentials are correct and the user logs in, the modalview is dismissed. and another viewcontroller is instantiated like this:
[self dismissModalViewControllerAnimated:NO];
Form *formcontroller = [[Form alloc] init];
[self presentModalViewController:formcontroller animated:YES];
When my other viewcontroller is presented the old one disappears. On the top of my secondviewcontroller i got an logout button, wich does exactly the same, so it dismisses the current viewcontroller and calls another like this:
-(IBAction)logOut:(id)sender{
[self dissmissModalViewControllerAnimated:NO];
}
And in my viewdiddisappear:
-(void)viewDidDisappear:(BOOL)animated{
Postform3ViewController *logincontroller = [[Postform3ViewController alloc] init];
[self presentModalViewController:logincontroller animated:YES];
}
The problem is:
When i push the logout button, and i return back to the logincontroller. The Credentials are still filled in. So my conclusion is that the first viewcontroller stays in memory. What am i doing wrong?
Edit:
I did find my own solution. I was profiling my application, and couldn't find any memory leaks. So i decided everything is released. Then i thought that i was able to set everything to empty myself. I did that in the viewDidAppear method like this:
-(void)viewDidAppear:(BOOL)animated {
gebruikersnaam.text = #"";
wachtwoord.text = #"";
[self.activeTextField resignFirstResponder];
[super viewDidAppear:animated];
}
Well first of all when you are using presentModalViewController and pushViewController the VC is retained so you should always release it after you have presented or pushed it.
Secondly in the third block of code it looks like you are creating a logincontroller but presenting a formcontroller. Perhaps you want to be presenting the VC you had just created:
[self presentModalViewController:logincontroller animated:animated];
Edit 0: For your code, in the first block, release like this:
Form *formcontroller = [[Form alloc] init];
[self presentModalViewController:formcontroller animated:YES];
...
[self dismissModalViewController:formcontroller animated:YES];
[formcontroller release];

objective-c modalViewController too quick

I am having an issue dismissing a modal view controller on a certain edge case. I display the modal view when I am retrieving a PDF to display in a UIWebView. When the file I am retrieving is very small the modal view will try to dismiss too soon. I present the modal view in the view controller that contains the UIWebView. I dismiss it in the UIWebView's didFinishLoad delegate method.
I am fine with not animating the initial presentation of the modal view... but is that any more safe than what I was doing? does this still have potential to fail, and if so how would you change it? I have been looking through the docs and nothing I have read so far adresses this situation.
//
// This will download the file if not # specific path, otherwise use local file.
// _myFileManager is a helper class and _myFileRecord is the backing data model
//
-(id)initWithNib... fileRecord:(MYFileRecord *)_myFileRecord
{
[_myFileManager cacheFileAsync:_myFileRecord delegate:self];
}
- (void)viewDidLoad
{
// doesn't seem to work, NO for animated does seem to work
[self.navigationController presentModalViewController:_splashController
animated:YES];
_splashController.messageLabel.text = #"Retrieving File...";
}
- (void)recordSaved:(MyFileRecord *)myFileRecord fileName:(NSString *)fileName
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:fileName]];
[_webView loadRequest:request];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
_splashController.messageLabel.text = #"Opening File...";
}
//
// This fails when a small file is already cached to disk and the time
// for the webView to finishLoad is faster than the splashView can present itself
//
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
Try implementing the viewDidAppear in your SplashController, to catch when the view has finished animating, and set a flag. Then you can control if the SplashController's view has finished loading using this flag, and wait for it if it is not finished yet?
E.g.
-(void)viewDidAppear {
if (shouldDismiss) {
[self dismissViewControllerAnimated:YES];
}
readyToDismiss = YES;
}
And in your main VC:
-(void)webViewDidFinishLoading:(UIWebView*)webViewv
{
if (_splashController.readyToDismiss) {
[_splashController dismissViewControllerAnimated:YES];
} else {
_splashController.shouldDismiss = YES; // will dismiss in viewDidAppear
}
}
You can try testing to see if the splashView has finished and use performSelector:afterDelay: to check back later.
My idea is to create a method like this
-(void)dismissWhenReady {
if ( splashView is finished) {
[self.navigationController dismissModalViewControllerAnimated:YES];
} else
[self performSelector:#selector(dismissWhenReady) afterDelay:1.0];
}
}
viewDidLoad fires too early (before it is displayed), you will want to use -(void)viewDidAppear:(BOOL)animated to present your modal view instead along with a flag to know if it is the first load. If it still does not display long enough add a delay for the desired amount of time.