How to pop to the previous viewController automatically? - objective-c

I connected mainViewController and customTableViewController with a "push" segue. The mainViewController pass an array of data to customTableViewController in prepareForSegue. If the array is empty, customTableViewController should automatically pop back to the mainViewController.
My code looks like this:
//customTableViewController.m
- (void) viewDidload
{
if (self.array.count == 0) {
[self.navigationController popViewControllerAnimated: YES];
}
}
But all i got is a blank and black view if the array is empty, not the mainViewController.
If i call popViewControllerAnimated manually (such as pushing a button), everything just works as i expected. So, what should i do?
Thank you all in advance.

Try to use your code in -viewDidAppear:(BOOL)animated

Related

Calling reloadData on same UITableView, but it seems like it's calling on a different one

This has been a headache for few hours now and I finally found out what is actually happening, but I don't know how to solve this issue.
I've got List.h with UITableView properly connected from storyboard:
#property (strong, nonatomic) IBOutlet UITableView *tableView;
Then there's List.m where I set delegates and datasource for my UITableView:
// Set tableview datasource and register class for cell reuse
self.tableView.dataSource = self;
[self.tableView registerClass:[TableViewCell class] forCellReuseIdentifier:#"cell"];
// Set tableview delegate
self.tableView.delegate = self;
// Set tableview cells style
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.backgroundColor = [UIColor colorWithWhite:0.1f alpha:1.0f];
// Set tableview frame
self.tableView.frame = CGRectMake(0.0, 35.0, self.tableView.frame.size.width, self.tableView.frame.size.height-35.0);
Then on NSNotification I'm trying to [self.tableView reloadData]:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doUpdateAppBefore:) name:UIApplicationWillEnterForegroundNotification object:nil];
Also I'm reloading data of tableView on every UIApplicationBecomeActive notification.
Before I close my app and open it up from background to find out if it's reloads the data, I'm moving to another UIViewController and going back, which causes that somehow identifier of my self.tableView changes. I'm checking it in:
NSLog(#"Calling reloadData on : %#");
and at the beginning it gives me:
Calling reloadData on <UITableView: 0x9b09400;....
but after I segue back from another UIViewController it gives me:
Calling reloadData on <UITableView: 0x9b4b000;
which causes that it doesn't actually reload the data after I open up the app from the background state.
I've been thinking... when I segue back from another viewcontroller, viewDidLoad fires again, is it possible that it somehow sets tableView.delegate again and changes something? Just thinking...
Thank you very much for your answers.
It sounds like you have a view controller, push a modal view on top of it, and then want to go back to the original view controller when you're done. So, you set up a modal segue in your storyboard, and then a second modal segue to go back. The problem is that your second modal segue doesn't return to the original view controller, but it creates a new instance of that view controller, and now your have the original view controller, the second view controller, and an unwanted third view controller. Instead of creating a segue, which creates the third view controller, you need to dismiss the second view controller, which then gets you back to your original view controller, and therefore also your original table view. So what you want to do is get rid of the second segue and replace it with an IBAction, put something like
- (IBAction)goBack:(id)sender;
in your .h file. Connect that to your button or whatever you're using to trigger the segue now. Then, in your implementation file, dismiss the modal view like so:
- (IBAction)goBack:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
That should get you what you want.
Alternately, and this is probably better, you can use an unwind segue as well. Go to List.h, and create this method:
- (IBAction)unwind:(UIStoryboardSegue *)segue;
Then just implement it, you can leave it blank for now. Then, drag from the button that currently triggers the segue to Exit, and select the Action Segue unwind. That will also get you back.

View controller unset his tag when pushed into nevigation controller

... I guess.
This is the situation:
here a simple method, in a view controller, where we can push a botton to go in another view:
- (IBAction)actionNext:(UIButton *)sender {
self.numeriUtiliListaViewController = [[ALCNumeriUtiliListaViewController alloc] init];
[self.numeriUtiliListaViewController.view setTag:[sender tag]];
[self.delegate vai:self.numeriUtiliListaViewController title:#"Numeri Utili"];
}
the delegate's method is:
- (void)vai:(id)view title:(NSString *)title
{
ALCParentViewController *viewController = (ALCParentViewController *)view;
viewController.delegate = self;
NSLog(#"tag: %d",[viewController.view tag]);
[self.myNavigationController pushViewController:viewController animated:YES];
}
This system works well, but the only thing is the tag that i've logged in this last method, here it was print correctly, but in the view loaded by the navigation controller, when i try to catch the value in the viewDidLoad, it's 0.
Any ideas?
Thanks in advance
Update 1 2013-01-30:
if i try to print the the tag in the viewWilAppear method of the viewcontroller pushed in the navigationcontroller, i'll give the right value... why? i don't know
Whats happening here is that in your actionNext method, when you are setting the tag of the viewController's view using : self.numeriUtiliListaViewController.view, as soon as you access the view propert of the viewController, viewDidLoad method is called in the viewController. So even before the setTag function is executed, viewDidLoad has already been executed, and it is showing tag = 0. But your viewWillAppear/viewDidAppear methods will be called only when the actual view appears and by then setTag has been executed, so it shows correct value.
Makes sense? Hope this helps

pop and refresh viewcontroller

I have three viewcontroller. when I get to the third viewcontroller, I use poptorootviewcontroller to pop to my first view controller, but when I use popviewcontroller in my third viewcontroller (i want to go back to my second viewcontroller) its poping but all the info that I edit in my second viewcontroller are there, and I want the secondviewcontroller to be new (reset this viewcontroller), like this viewcontroller to be reloaded.
here is my code in the third viewcontroller:
-(IBAction)playAgain:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
how can I do it?
thanks!
In the second viewcontroller, you should write a method viewWillAppear like below,
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//set initial values here
}
This method will call when your controller is about to appear. So while third viewcontroller will get popped, this method will get called and you can reset values.

ipad detect when UIPopoverControllers are dismissed

I have several uiPopoverControllers in my universal iPad app. I now have a requirement to trigger a function once a certain popover has been dismissed. I can do this easily if the user clicks "close" inside the popover, but if they touch the screen to hide the popover, I cannot trigger my function.
I've been googling for some time and cannot seem to find any delegate methods which I might be able to use in my main view controller to capture them. I would love something like didDismissPopoverController - but my guess is it's not available.
IF not, I guess the only thing to do would be to detect the touches and trigger then? Basically I am highlighting a UITableView row and loading the popover. I need to deselect the row - so want to simply call [table reloaddata].
Thanks for any help on this one!
You need to assign a delegate to the UIPopoverController and then implement the - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController method. For example:
#interface FooController : UIViewController <UIPopoverControllerDelegate> {
// ...
}
// ...
#end
When you instantiate the UIPopoverController (say, for this example, in FooController)...
UIPopoverController *popover = // ...
popover.delegate = self;
Then, you would implement the method:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
// do something now that it's been dismissed
}
Granted, I haven't tested this but it seems like it should work...
Hope this helps!
You can use the popoverControllerDidDismissPopover delegate method after the following assignment:
self.popoverController.delegate = self;
Note that popoverControllerDidDismissPopover delegate method does not get called if you programmatically call [self.popoverController dismissPopoverAnimated:YES].

UIViewController parentViewController access properties

I know this question has been asked several times and I did read existing posts on this topic but I still need help.
I have 2 UIViewControllers - parent and child. I display the child UIViewController using the presentModalViewController as below:
ChildController *child =
[[ChildController alloc] initWithNibName:#"ChildView" bundle:nil];
[self presentModalViewController:child animated:YES];
[child release];
The child view has a UIPickerView. When user selects an item from UIPickerView and clicks done, I have to dismiss the modal view and display the selected item on a UITextField in the parent view.
In child's button click delegate, I do the following:
ParentController *parent =
(ParentController *)[self.navigationController parentViewController];
[parent.myTextField setText:selectedText];
[self dismissModalViewControllerAnimated:YES];
Everything works without errors. But I don't know how to load the parent view so that it displays the updated UITextField.
I tried
[parent reloadInputViews];
doesn' work. Please help.
Delegation is the way to go. I know some people that may be looking for an easier solution but trust me I have tried others and nothing works better than delegation. So anyone having the same problem, go read up on delegation and follow it step by step.
In your subviewcontroller.h - declare a protocol and declare delegate mthods in it.
#protocol myDelegate
-(void)clickedButton:(subviewcontroller *)subController;
#end
In your subviewcontroller.h, within #interface:
id<myDelegate> delegate;
#property (nonatomic, assign) id<myDelegate> delegate;
NSString *data;
-(NSString *)getData;
In your subviewcontroller.m, synthesize myDelegate. Add the following code to where you want to notify your parentviewcontroller that the subview is done doing whatever it is supposed to do:
[delegate clickedButton:self];
and then handle getData to return whatever data you want to send to your parentviewcontroller
In your parentviewcontroller.h, import subviewcontroller.h and use it's delegate
#import "subviewcontroller.h"
#interface parentviewcontroller : VUIViewController <myDelegate>
{}
In your parentviewcontroller.m, implement the delegate method
- (void)clickedButton:(subviewcontroller *)subcontroller
{
NSString *myData = [subcontroller getData];
[self dimissModalViewControllerAnimated:YES];
[self reloadInputViews];
}
Don't forget memory management!
If a low-memory warning comes in during your modal view's display, the parent's view will be unloaded. Then parent.myTextField is no longer referring to the right text field until the view is reloaded. You can force a reload of the view just by calling parent.view;
However, a better idea might be to have the parent view have a String property that can be set by the child view. Then, when the parent view reappears, put that data into the text field, inside viewWillAppear: for example. You'd want to have the value set to some default value for when the parent view initially shows up too.
-(void) viewWillAppear:(BOOL) animated doesn't get called for me either, exactly when it's a modal view controller. No idea why. Not incorrectly overridden anywhere in this app, and the same problem occurs on the other 2 apps I'm working on. I really don't think it works.
I've used the delegate approach before, but I think that following approach is pretty good as well.
I work around this by adding a private category to UIViewController, like so:
.h file:
#interface UIViewController(Extras)
// returns true if this view was presented via presentModalViewController:animated:, false otherwise.
#property(readonly) BOOL isModal;
// Just like the regular dismissModalViewController, but actually calls viewWillAppear: on the parent, which hasn't been working for me, ever, for modal dialogs.
- (void)dismissModal: (BOOL) animated;
#end
and .m file:
#implementation UIView(Extras)
-(BOOL) isModal
{
return self == self.parentViewController.modalViewController;
}
- (void)dismissModal: (BOOL) animated
{
[self.parentViewController viewWillAppear: animated];
[self dismissModalViewControllerAnimated: animated];
}
#end
which I can now call like this when I want to dismiss the dialog box:
// If presented as a modal view, dismiss yourself.
if(self.isModal)
[self dismissModal: YES];
and now viewWillAppear is correctly called.
And yes, I'm donating a bonus 'isModal' property, so that the modal view can tell how it was being presented, and dismiss itself appropriately.