Reputation: 433
I have a HomeViewController
which has a tableView populated with the array tableViewArray
(originally empty). When I tap on a barButton, I segue modally to another View Controller called OutsideViewController
which has another tableView populated by a different array.
What I would like to do is the following:
When I tap on a row in my OutsideViewController
, I would like to add the selected string value to the tableViewArray
so that when I go back to HomeViewController
, the tableView has that new item listed in the tableView.
So far, this is what I have tried:
In the -didSelectRowAtIndexPath
method of my OutsideViewController.m
I have this piece of code:
NSString *selectedRow = [outsideArray objectAtIndex:indexPath.row];
NSMutableArray *temporaryArray = [NSMutableArray arrayWithObject:selectedRow];
HomeViewController *homeVC = [[HomeViewController alloc] init];
homeVC.tableViewArray = temporaryArray;
That code works but the tableView in HomeViewController
is still empty when I return. Do I have to reload the tableView data?
Am I doing this right?
This is how I have set up my View Controllers in Storyboard:
HomeViewController -(modal segue)-> Navigation Controller --> OutsideViewController
Also, the return from OutsideViewController to HomeViewController is done by this line of code:
[self dismissViewControllerAnimated:YES completion:^{ }];
Upvotes: 3
Views: 6575
Reputation: 4914
First of all make sure you alloc
, init
your tableViewArray
in HomeViewController
Second , In this line
HomeViewController *homeVC = [[HomeViewController alloc] init]
you are creating a new reference to your HomeViewController
which is not correct, you need to pass correct reference, possibly creating HomeViewController variable in your OutsideViewController
Even though you correctly do first and second suggestion you will still see an empty tableview because you dont reload the tableview, somehow you need to fire [self.tableview reloadData];
method.
That means; you need to learn Delegate or NSNotifications pattern to communicate between child->parent scenarios
How do I set up a simple delegate to communicate between two view controllers?
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_nsnotificationcenter/
For your question just create a delegate in your Outside
;
in your OutsideViewController.h
#import <UIKit/UIKit.h>
@protocol OutsideDelegate;
@interface{}//bunch of interface stuff
// Declare a property for the delegate
@property (weak) id <OutsideDelegate> delegate;
@end
// Protocol Header
@protocol OutsideDelegate <NSObject>
@optional
- (void)dismissPop:(NSMutableArray *)list;
@end
in your OutsideViewController.m
@synthesize delegate;
//run delegate method
[delegate dismissPop:temporaryArray];
[self dismissViewControllerAnimated:YES completion:^{ }];
in your HomeViewController.h
#import "OutsideViewController.h"
@interface OutsideViewController : UITableViewController<OutsideDelegate>
{}
@property (strong, nonatomic) OutsideViewController *pvc;
in your HomeViewController.m
@synthesize pvc;
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"your segue"]) {
pvc = [segue destinationViewController];
[pvc setDelegate:self];
}
}
// delegate callback function
- (void)dismissPop:(NSMutableArray *)list {
self.tableViewArray=list;
[self.tableView reloadData];
}
Another Solution Would be
Change your view stack to this:
Navigation Controller --> HomeViewController -(push segue)--> OutsideViewController
and apply rdurand's answer
and add this to your HomeViewController :
-(void)viewDidAppear:(BOOL)animated
{
[self.tableview reloadData];
}
In this solution since you are just push-pop viewcontrollers in a nabigation stack viewDidAppear
will be called in HomeViewController everytime when you pop OutsideViewController.
Upvotes: 0
Reputation: 691
You can achieve this too using delegation. You have to create a protocol in your OutsideViewController
with a method that is responsible for sending the new object to your HomeViewController
. Do this in OutsideViewController.h:
@protocol OutsideViewDelegate <NSObject>
- (void)OutsideViewController:(OutsideViewController *)controller didAddObject:(NSString *)object;
@end
In the implementation file you have to change a little bit the didSelectRowAtIndexPath:
method:
NSString *selectedRow = [outsideArray objectAtIndex:indexPath.row];
[self.delegate OutsideViewController:self didAddObject:selectedRow];
In your HomeViewController.h you have to make your class conforms to the protocol:
@interface HomeViewController : UIViewController <OutsideViewDelegate>
After, create a property for the delegate:
@property (nonatomic, weak) id <OutsideViewDelegate> delegate;
To finish the process, implement the protocol in your HomeViewController.m to receive the new object from the OutsideViewController:
- (void)OutsideViewController:(OutsideViewController *)controller didAddObject:(NSString *)object
{
if (object != nil)
{
[self.tableViewArray addObject:object];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
The code above depends of if your tableViewArray
object is mutable or not. If it's not, you can change the type of the object argument in the protocol method to an inmutable array object and just assign tableViewArray
to the new array.
EDIT:
In the prepareForSegue:
method don't forget to set the delegate:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"SEGUE_IDENTIFIER"]) {
OutsideViewController *outsideVC = (OutsideViewController *)[segue destinationViewController];
[outsideVC setDelegate:self];
}
}
Upvotes: 1
Reputation: 7410
What you're doing wrong is you're allocationg a new HomeViewController
. What I would do is keeep a reference to your HomeViewController
in your OutsideViewController
. Here is how.
First, in OutsideViewController.h
, create a property, like this :
@property (nonatomic, weak) HomeViewController *homeVC;
Don't forget to add @class HomeViewController;
in your .h, and #import "HomeViewController.h"
in your .m
In HomeViewController
, implement the prepareForSegue:
method like this (replace ModalSegueIdentifier with your segue's identifier) :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"ModalSegueIdentifier"]) {
OutsideViewController *modalVC = (OutsideViewController*)segue.destinationViewController;
modalVC.homeVC = self;
}
}
Then, in OutsideViewController.m
, instead of doing :
HomeViewController *homeVC = [[HomeViewController alloc] init];
homeVC.tableViewArray = temporaryArray;
Do this :
_homeVC.tableViewArray = temporaryArray;
When you leave your modal VC, your HomeVC will have the correct array. Don't forget to refresh your UITableView
!
NB: Of course, there are many other ways, and it's maybe not the best one. But still, it should work.
Upvotes: 4