Reputation: 345
I have a tableview as a parent view controller with a child modal view controller. In the modal view controller, when users tap on a row, I'd like to set the parent's property 'filter.' However, it's just returning null.
How do I pass the NSString filter property back to its parent view? And should I be instantiating a parent view controller in the didSelectRowAtIndexPath method?
UPDATE: Solved using Delegates, followed this tutorial.
Below is the code for the modal view controller:
#import "FilterViewController.h"
#import "ContactsTableViewController.h"
@interface FilterViewController ()
@end
@implementation FilterViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.filterTable.dataSource = self;
self.filterTable.delegate = self;
[self performSelector:@selector(retrieveFilteredEvents)];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.filterEvents count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = @"filterTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSDictionary *tempDict = [self.filterEvents objectAtIndex:indexPath.row];
self.eventTitle = [tempDict objectForKey:@"eventType"];
cell.textLabel.text = self.eventTitle;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *tempDict = [self.filterEvents objectAtIndex:indexPath.row];
NSString *string = [tempDict objectForKey:@"eventType"];
ContactsTableViewController *contactVC = [[ContactsTableViewController alloc] init];
contactVC.filter = string;
[self dismissViewControllerAnimated:YES completion:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"updateParent" object:nil];
}
#pragma mark - Helper Methods
- (IBAction)done:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)retrieveFilteredEvents
{
PFQuery *retrieveEvents = [PFQuery queryWithClassName:@"eventTypes"];
[retrieveEvents orderByAscending:@"eventOrder"];
[retrieveEvents findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.filterEvents = [[NSArray alloc] initWithArray:objects];
}
[self.filterTable reloadData];
}];
}
@end
Upvotes: 1
Views: 1533
Reputation: 31
If it's a simple property set, you could do
[self.parentViewController performSelector:@selector(setSomething:) withObject:...]
or
[self.presentingViewController performSelector:@selector(setSomething:) withObject:...]
Delegates is a much better way, though :-)
Upvotes: 0
Reputation: 395
There are multiple ways to approach this problem. The easiest I think would be setting a property in your parent class that would change every time you update the child.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *tempDict = [self.filterEvents objectAtIndex:indexPath.row];
NSString *string = [tempDict objectForKey:@"eventType"];
self.parentViewController.filter = string;
[self dismissViewControllerAnimated:YES completion:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"updateParent" object:nil];
}
The other option would be to use delegates. This is probably a cleaner solution but is not as beginner friendly.
http://iosdevelopertips.com/objective-c/the-basics-of-protocols-and-delegates.html
Upvotes: 3
Reputation: 13947
create a protocol
@protocol PassSomeData
-(void)childViewController:(UIViewController *)viewController passedSomeData:(id)data;
@end
create a delegate in the childview controller
@interface ViewControllerThatIsPresentedModally :UIViewController
@property(nonatomic,assign) id<PassSomeData>delegate;
@end
in prepareForSegue
of the view controller that is presenting the modal write this
UIViewController *vc = [segue destinationViewController];
if ([vc isKindOfClass:[ViewControllerTahIsPresentedModally class]){
[((ViewControllerThatIsPresentedModally *)vc) setDelegate:self];
}
when your user clicks something that allows some data to be collected you do
[self.delegate viewController:self passedSomeData:yourData];
and your method in the parent view controller will be called with your data
your presenting view controller needs to conform to the PassedSomeData protocol and implement the given method as well
Upvotes: 2
Reputation: 4651
Alloc init gives you a brand new object, NOT a reference to your existing one. There are a couple of ways to get a reference to your table view. I recommend delegation, it's a flexible approach that will continue to work even if you present your view in a different way than modal.
Upvotes: 2
Reputation: 69047
What you are doing here:
ContactsTableViewController *contactVC = [[ContactsTableViewController alloc] init];
contactVC.filter = string;
is instantiating a whole new controller that has nothing to do with the actual controller that presented your FilterViewController
.
Try using this, instead, which accesses the view controller that presented FilterViewController
:
ContactsTableViewController *contactVC = (ContactsTableViewController*)self.presentingController;
contactVC.filter = string;
Hope this helps.
Upvotes: 3