views:

740

answers:

2

I have a UITableView and inside it I create a custom UITableViewCell in the follwoing way:

ItemCellController *cell = (ItemCellController *)[tableView dequeueReusableCellWithIdentifier:ContentListsCellIdentifier];
...
cell = [[[ItemCellController alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ContentListsCellIdentifier] autorelease];

I do this to can get touchesBegan and touchesEnded events (so that I can implement a long touch). Using NSLog I can see that the longTouch is called properly from within the touchesBegan method using the following code:

timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(longTouch:) userInfo:nil repeats:YES];

The problem is that I am not able to call a modal window from within the longTouch method.

I tried the following, but I get an NSInvalidArgumentException -[ItemCellController navigationController]: unrecognized selector sent to instance error.

AddItemController *addView = [[AddItemController alloc] initWithNibName:@"AddItemView" bundle:nil];  

UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:addView];
controller.navigationBar.barStyle = UIBarStyleBlack;
[[self navigationController] presentModalViewController:controller animated:YES];
[controller release];

So the question is, how can I call up a modal window from within a custom UITableViewCell.

Thanks

A: 

It does not look like you set the cells navigation controller anywhere, it seems that it does not like [[self navigationController] presentModalViewController:controller animated:YES]; that line, check the nagivationController property on that "self" object

Daniel
+1  A: 

The navigationController property exists for UIViewControllers, but UITableViewCell (which I guess ItemCellController is a subclass of) is not a UIViewController, so it doesn't have that property by default.

There are a few appraoches:

(1) Add a UIViewController* property (maybe call it controller) to your custom cell type, and pass in a pointer to your controller with your init method (say, initWithController:). Then in your cell, you can just execute:

UINavigationController* navController = [ /* alloc and init it */ ]
[self.controller presentModalViewController:navController animated:YES];

(2) Your app delegate object could have a controller property that you can access from anywhere in your code. Then you could do something like this:

MyAppDelegate* myAppDelegate = [[UIApplication sharedApplication] delegate];
[myAppDelegate.controller presentModalViewController:navController
                                            animated:YES];

(3) This one is less direct but more flexible. You could set up your root controller (the one you want to do the presenting of the modal view) to listen for a certain notification, and post that notification from within your table cells.

Sample listen code, called from within your root controller:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(showModal:)
                                             name:@"show modal"
                                           object:nil];

Sample post code, called from within a table cell:

NSDictionary* userInfo = [ /* store a handle to your modal controller */ ];
[[NSNotificationCenter defaultCenter] postNotificationName:@"show modal"
                                                    object:self
                                                  userInfo:userInfo];

And the showModal: method of your root controller would use the userInfo included in the NSNotification to figure out which view controller to present modally. That's more work, but it would automatically allow any of your code anywhere to present a modal view, without giving them full access to a root controller pointer.

Tyler
Wow. The notification method is great! It really cleans things up a lot. Thanks.
Mario