I am using John Lluch's SWRevealViewController which works great, except I cannot figure out how to set selectors in the destination view controller as I do in segues for other UIViewControllers.
Has anyone else encountered this problem?
Here is my code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Set the title of navigation bar by using the menu items
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
if ([segue.identifier isEqualToString:#"goalSegue"]) {
if ([segue.destinationViewController respondsToSelector:#selector(setTitleForViewController:)]) {
// use performSelector:withObject: to send without compiler checking
// (which is acceptable here because we used introspection to be sure this is okay)
NSString * titleText = #"Athlete Goals";
[segue.destinationViewController performSelector:#selector(setTitleForViewController:) withObject:titleText];
} else destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
} else destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
}
I have used this code in prepareForSegue in other view controllers. The selector exists in the destination TableViewController, but SWRevealViewController passes over if-statement without executing.
I think the problem lies in the fact that you are trying to run a selector method on a UINavigationController and not the actual TableViewController in which the selector resides. Notice that destViewController is a UINavigationController, which has your TableViewController inside it.
So actually, you can try the following code and see if it works (I've tried this in a sample project using SWRevealViewController and it works)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Set the title of navigation bar by using the menu items
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
YourTableViewController *tableController = (YourTableViewController *)[destViewController childViewControllers].firstObject;
if ([segue.identifier isEqualToString:#"goalSegue"]) {
if ([tableController respondsToSelector:#selector(setTitleForViewController:)]) {
NSString * titleText = #"Athlete Goals";
[tableController performSelector:#selector(setTitleForViewController:) withObject:titleText];
} else destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
} else destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
}
As far as I understand, this may not exactly be a problem with SWRevealViewController.
Hope this helps.
Related
I have a small problem with an app where a debug I made there must be a conflict in a prepareForSegue: Let me explain
I have a UITableView with an array of data written by me.
Then I have another array with data of a xcdatamodel that the user must edit and save.
if I run with this screen prepareForSegue me when I call a cell crashes.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DetailSchedule"]) {
NSManagedObjectModel *selectedSche = [schedule objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
DetailMainHallTableViewController *destViewController = segue.destinationViewController;
DetailMainHallTableViewController *dc = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
dc.mainhall = self.myArraySchedule1[indexPath.row];
destViewController.sche = selectedSche;
}
}
but if I run with this screen of the app runs prepareForSegue okay but I did not save the entered data
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"DetailSchedule"]) {
//NSManagedObjectModel *selectedSche = [schedule objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
DetailMainHallTableViewController *destViewController = segue.destinationViewController;
DetailMainHallTableViewController *dc = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
dc.mainhall = self.myArraySchedule1[indexPath.row];
//destViewController.sche = selectedSche;
}
}
It is strange, however, that if we take off // and I run again the data I had entered before appearing saved me and I can edit them or add them.
Can these two lines to understand the problem?
If you are using a UITableView you should move the NSManagedObjectModel code to the tableView:didSelectRowAtIndexPath method and then send that object as the sender for your segue.
I am so tired of trying to make this work so i hope somebody here will be able to solve this for me..
I am using this code to segue to a UINavigationController. This code WORKS on simulator but NOT on a real device:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
static NSString *segueIdentifier = #"ShowDetails";
if ([[segue identifier] isEqualToString:segueIdentifier]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *navigationController = segue.destinationViewController;
DetailViewController *detailViewController = [navigationController viewControllers][0];
detailViewController.selectedGameIdNumber = [NSString stringWithFormat: #"%ld", (long)indexPath.row];
detailViewController.selectedSection = [self.sectionNames objectAtIndex:indexPath.section];
}
}
On the real device it crashes at:
DetailViewController *detailViewController = [navigationController viewControllers][0];
with the error:
-[DetailViewController viewControllers]: unrecognized selector sent to instance
Then i have this code that i tried. This code WORKS on device but NOT on simulator:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
static NSString *segueIdentifier = #"ShowDetails";
if ([[segue identifier] isEqualToString:segueIdentifier]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailViewController * detailViewController = (DetailViewController *)segue.destinationViewController;
detailViewController.selectedGameIdNumber = [NSString stringWithFormat: #"%ld", (long)indexPath.row];
detailViewController.selectedSection = [self.sectionNames objectAtIndex:indexPath.section];
}
}
On the simulator it crashes at:
detailViewController.selectedGameIdNumber = [NSString stringWithFormat: #"%ld", (long)indexPath.row];
With the error:
-[UINavigationController setSelectedGameIdNumber:]: unrecognized selector sent to instance 0x7fa1d273e8
Am i doing something wrong or should i just run with the second code that works on real device?
I want to have a clean solution so please do enlighten me if i am doing something wrong. Thank you all.
The issue is with how you are accessing the view controller. On the device the view controller hierarchy is different from on the simulator, and so the two solutions both only work in their own scenario. Of course it isn't the simulator that is different, but rather the device you are simulating (guess is iPad)
Be aware that, especially with splitViewcontrollers, but also with other framework provided view controllers that the functionality of the controllers may vary based on the target device. This change often bites you when you make assumptions about indexes of view controllers and the like.
Debug on the simulator, switching between device types and po the view controller and I think you will see what I mean.
Here's my solution: creating a generic struct and cast the customized viewcontroller by function call. The advantage is that you can reuse this function everywhere you need it.
(Though my code is in written in swift rather than Objective-C, I think the way of solution is just alike)
struct DestinationController<T: UIViewController> {
func get(segue: UIStoryboardSegue) -> T {
if let navigation = segue.destinationViewController as? UINavigationController{
return navigation.viewControllers.first as! T
}
return segue.destinationViewController as! T
}
}
i have a project which is basically a uitableview populated with a mutable array and has a search bar
now the uitableview has title and subtitle which are populated with different mutable arrays ..
when you tap on a cell (from the view or from the search view) it pushes the title to a new view controller.
i need the subtitle to be pushed also to the new view controller
i tried every thing i know but i had no success
i have attached the project so you can see how its coded and possibly tell me how to fix it
http://ezzati.net/KuwaitFood.zip
please help
Please replace the function below.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowDetail"]) {
NSString *object = nil;
NSIndexPath *indexPath = nil;
if (self.searchDisplayController.isActive) {
indexPath = [[self.searchDisplayController searchResultsTableView] indexPathForSelectedRow];
object = self.results[indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
object = self.objects[indexPath.row];
}
[[segue destinationViewController] setDetailLabelContents:object];
[[segue destinationViewController] setNumberdetailLabelContents:[sender detailTextLabel].text];
}
}
You have to assign a identifier to the segue (the arrow from your table view controller to the new controller in your storyboard) and then use this function to grab the destination view controller and set it's property with the data you want to send:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"identifier"])
{
SecondViewController *vc = [segue destinationViewController];
// get the selected item index
NSInteger index = [self.tableView indexPathForCell:sender].row;
// set the data property for the second view (pass data)
vc.theProperty = [self.data objectAtIndex:index];
}
Now you can find theProperty on your SecondViewController filled with data from the table view controller.
EDIT: I've reviewed your code. for your case do this:
in -tableView: didSelectRowAtIndexPath: change self to indexPath like this:
[self performSegueWithIdentifier:#"ShowDetail" sender:indexPath];
and in prepareForSegue do this:
DetailViewController *vc = [segue destinationViewController];
// get the selected item index
NSInteger index = ((NSIndexPath *)sender).row;
// index of searched object in self.objects
NSInteger trueIndex = [self.objects indexOfObject:[self.results objectAtIndex:index]];
// set the data property for the second view (pass data)
vc.detailLabelContents = [self.objects objectAtIndex:trueIndex];
vc.numberdetailLabelContents = [self.numbers objectAtIndex:trueIndex];
the problem was because you were using index of self.results and applying it to self.objects which was 0, so you were always getting the first object "You Tube"
change the last line of
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
as below
[[segue destinationViewController] setDetailLabelContents:[sender detailTextLabel].text];
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"DetailPlacePage"]) {
NSIndexPath *indexPath = [self.Allplace indexPathForSelectedRow];
NomadPlaceDetailViewController *placedetailcontroller = segue.destinationViewController;
placedetailcontroller.myDictionary = [self.placeArray objectAtIndex:indexPath.row];
}
}
This is the code I use to prepare segue for UIviewcontroller.
Can't see the next view controller , screen gets blank and just navigation bar is shown .
Try casting your NomadPlaceDetailViewController:
NomadPlaceDetailViewController *placedetailcontroller = (NomadPlaceDetailViewController *)segue.destinationViewController;
So I have a UITableView, and the cells are connected to a UIStoryboardSegue in order to open a new UIViewController. After clicking a cell prepareForSegue get's called and everything works fine.
QUESTION: In the follwoing method how can i know what is the indexPath of the selected cell in my TableView?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ObjectDetailViewController *mvc = [segue destinationViewController];
// PassingObject *obj = [self.array objectAtIndex: ? ];
mvc.passingObject = obj;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Assume self.view is the table view
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
DetailObject *detail = [self detailForIndexPath:path];
[segue.destinationViewController setDetail:detail];
}
Instead of [self.tableView indexPathForSelectedRow] (look at the DJPlayer answer) you can use [self.tableView indexPathForCell:sender], since sender is a selected cell in this case.