I have a navigation controller and the first VC modals into the second one fine. I pressed ctrl+button and dragged it over, all works fine.
I am doing a second segue from the first VC (again) and this time its another button, I am ctrl+button and dragging it to the new VC and I get an USELESS error in XCODE -
2014-03-04 11:57:21.340 OutTonight[3173:60b] -[SettingsViewController
setDealdetail:]: unrecognized selector sent to instance 0x16e686d0
2014-03-04 11:57:21.342 OutTonight[3173:60b] * Terminating app due
to uncaught exception 'NSInvalidArgumentException', reason:
'-[SettingsViewController setDealdetail:]: unrecognized selector sent
to instance 0x16e686d0'
* First throw call stack:
Here is my prepareforseguecode
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableview indexPathForSelectedRow];
DealViewController *detailView = (DealViewController *)segue.destinationViewController;
detailView.dealdetail = [self.allcontent objectAtIndex:indexPath.row];
detailView.dealpostcode = [self.allpostode objectAtIndex:indexPath.row];
detailView.dealvenuename = [self.allname objectAtIndex:indexPath.row];
detailView.dealaddress = [self.alladdress objectAtIndex:indexPath.row];
detailView.dealaddress2 = [self.alladdress2 objectAtIndex:indexPath.row];
detailView.deallat = [self.alllat objectAtIndex:indexPath.row];
detailView.deallng = [self.alllong objectAtIndex:indexPath.row];
detailView.userlatitude = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserLatitude"];
detailView.userlongitude = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserLongitude"];
}
Any ideas?
I assume you have done something in -prepareForSegue: for the original segue? In which case, you need to make sure you are checking which segue it is in -prepareForSegue:, and doing the correct thing for each one.
Edit:
To expand on my answer, I guess you are using segue.destinationViewController, and calling setDealdetail: on it. This probably worked fine for your initial segue, because the destinationViewController responded to that message, but, the destination for the new segue doesn't. You need to check which segue is being performed. Using [segue.identifier isEqualToString:MySegueIdentifierString];
Edit 2 (after posting code):
Ok, you need to check which segue is being performed in your -prepareForSegue:. Something like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:SegueToDealViewControllerIdentifier]) {
NSIndexPath *indexPath = [self.tableview indexPathForSelectedRow];
DealViewController *detailView = (DealViewController *)segue.destinationViewController;
detailView.dealdetail = [self.allcontent objectAtIndex:indexPath.row];
detailView.dealpostcode = [self.allpostode objectAtIndex:indexPath.row];
detailView.dealvenuename = [self.allname objectAtIndex:indexPath.row];
detailView.dealaddress = [self.alladdress objectAtIndex:indexPath.row];
detailView.dealaddress2 = [self.alladdress2 objectAtIndex:indexPath.row];
detailView.deallat = [self.alllat objectAtIndex:indexPath.row];
detailView.deallng = [self.alllong objectAtIndex:indexPath.row];
detailView.userlatitude = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserLatitude"];
detailView.userlongitude = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserLongitude"];
}
}
Where SegueToDealViewControllerIdentifier is the segue identifier for the original segue.
Related
I'm just trying send the mid to customerDetailviewcontroller and segue is going tabbar controller first.
There is my prepareforsegue method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ApiClass *apiClass = [self.customerCards objectAtIndex:indexPath.row];
CustomerDetailViewController *customerDetailViewController = (CustomerDetailViewController *)segue.destinationViewController;
customerDetailViewController.mid = apiClass.mid;
}
}
_mid NSString * #"1642"
That is the error.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITabBarController setMid:]: unrecognized selector sent to instance 0x126e53580'
*** First throw call stack:
(0x1838d6530 0x1948ac0e4 0x1838dd5f4 0x1838da3ac 0x1837dec4c 0x1000ae2b4 0x1886b401c 0x18820ce14 0x1882ca6dc 0x188166b8c 0x1880d85f0 0x18388ed98 0x18388bd24 0x18388c104 0x1837b91f4 0x18cbdb6fc 0x18814a10c 0x1000e2b08 0x194f2aa08)
libc++abi.dylib: terminating with uncaught exception of type NSException
There is the data I'm getting from json.So it is not nil.
http://prntscr.com/6lzjkd
I figure out this.Main Problem I push the segue to tabbar controller.And I fixed it with this code.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ApiClass *apiClass = [self.customerCards objectAtIndex:indexPath.row];
UITabBarController *tabBarController = [segue destinationViewController];
CustomerDetailViewController *customerDetailViewController = (CustomerDetailViewController *)[[tabBarController viewControllers]objectAtIndex:0];
customerDetailViewController.mid = apiClass.mid;
}
It is trying to execute the method setMid:, but it can't find that one. Did you set the property mid as readwrite?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowWordDetailsTwo"]) {
NSIndexPath *indexPath = nil;
Words *word = nil;
indexPath = [self.tableView indexPathForSelectedRow];
word = [myFavsTwo objectAtIndex:indexPath.row];
DetailsViewController *destViewController = segue.destinationViewController;
destViewController.word = word;
}
}
I'm getting a crash on segue -- breakpoint at:
destViewController.word = word;
but if I "continue" on my debugger everything will work as normal -- the app just seems to be getting hung up on this line...
I think it's got to do with my object being part of NSUserDefaults with NSCoder...
how can I make it so that the app doesn't crash?!
I'm not getting any error message just a break point error
Just clarifying,
Did you create the breakpoint yourself, or was it autocreated by the debugger?
Try disabling the breakpoint to see if it works.
I have a tableView where I can select a ship from a list, and when I tap it I want the information to pop up on another screen. The way I am currently doing this is:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
cargoShips* ship=[boatsForOwner objectAtIndex:indexPath.row];
UITableViewCell *cell = [self.boatsTableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"boatInfoSegue" sender:cell];
NSString *nameString = ship.name;
NSString *sizeString = ship.size;
NSUserDefaults *shipName = [NSUserDefaults standardUserDefaults];
[shipName setObject:nameString forKey:#"globalName"];
[shipName synchronize];
NSUserDefaults *shipSize = [NSUserDefaults standardUserDefaults];
[shipSize setObject:sizeString forKey:#"globalSize"];
[shipSize synchronize];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
And to load it back into text (in another file)
NSString *getName = [[NSUserDefaults standardUserDefaults]
objectForKey:#"globalName"];
NSString *getSize = [[NSUserDefaults standardUserDefaults]
objectForKey:#"globalSize"];
shipNameText.text = getName;
shipSizeText.text = getSize;
Now , this works great, except for the fact that it does not return the cell I selected to get to the infoView, but the previous selected object. So if I select the first object on the list, it returns null, the next item i select gets the result I should have had for the first object and so on.
What did I do wrong and how can I fix it?
NSUserDefaults is tool for saving settings, not for transferring object.
If I were you I made it this way:
#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender {
if ([segue.identifier isEqualToString:#"boatInfoSegue"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
CargoShip *ship = boatsForOwner[indexPath.row];
BoatViewController *vc = (BoatViewController *)segue.destinationViewController;
vc.ship = ship;
}
}
Class names should be capitalized, that's why I wrote CargoShip
From what I can see in your code. your problem is that you first perform the seque and then update the values in the NSUserDefaults move this line [self performSegueWithIdentifier:#"boatInfoSegue" sender:cell]; to the end of the method.
This should make it work, but you need to refactor you code.
Hey there I have been working on a transit app for some time and have been stuck with this issue for a while now.
I am using iOS 5 and a storyboard. Basically I have a UITableView that displays favorite bus stop locations, when a user selects a row I use:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Favorite *favorite = [self.favoriteItems objectAtIndex:indexPath.row];
stopString = favorite.title;
routeString = favorite.subtitle;
}
With the stop and route information of the cell the user chose I then prepare for a segue that corresponds to a segue on my storyboard, pushing a detail view controller that uses the stop name and route name to display times from a plist.
I am fairly new to Objective C and iOS so I am using a segue that my friend told me would work, however, it might be the problem. The segue looks like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *destination = segue.destinationViewController;
if ([destination respondsToSelector:#selector(setDelegate:)])
{
[destination setValue:self forKey:#"delegate"];
}
if ([destination respondsToSelector:#selector(setSelection:)])
{
NSString *route = routeString;
NSDictionary *selection1 = [NSDictionary dictionaryWithObjectsAndKeys:route, #"route", stopString, #"stop", nil];
[destination setValue:selection1 forKey:#"selection"];
}
}
After the segue in my DetailViewController I grab the stop and route information in the view DidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
route = [selection objectForKey:#"route"];
stopName = [selection objectForKey:#"stop"];
NSLog(#"stopName: %#", stopName);
NSLog(#"routeName: %#", route);
}
Here is where my problems arise. When I run the simulator and click on an a cell in my table view, I am pushed to the DVC, however, the stopName and routeName are both null, so no information was sent or received. BUT, if I go back to the table and click another cell, the routeName and stopName are filled with the information that should have sent the first time I clicked a cell. If I continue this process it continues to send the information for the cell tapped previously, not currently.
So basically information is sending but only after I go through the segue twice. Obviously I want it to send the information and receive it the first time, but it is delayed and driving me nuts. I appreciate any help someone can give me as I have been searching the internet for days now trying to fix this issue, thank you so much in advance for any assistance!
prepareForSegue: is being called before didSelectRowAtIndexPath:. This is why the values you see always are lagging behind.
The better solution is to get the stopString and routeString values in your prepareForSegue: method (and not use didSelectRowForIndexPath: at all). The key to doing this is to realize that the sender parameter value being passed to prepareForSegue: is the UITableViewCell that was tapped. You can use the UITableView method indexPathForCell to get the cell's indexPath in your table, and then use that to look up the data in your favoriteItems array.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UITableViewCell *cell = (UITableViewCell*)sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
Favorite *favorite = [self.favoriteItems objectAtIndex:indexPath.row];
stopString = favorite.title;
routeString = favorite.subtitle;
UIViewController *destination = segue.destinationViewController;
if ([destination respondsToSelector:#selector(setDelegate:)])
{
[destination setValue:self forKey:#"delegate"];
}
if ([destination respondsToSelector:#selector(setSelection:)])
{
NSString *route = routeString;
NSDictionary *selection1 = [NSDictionary dictionaryWithObjectsAndKeys:route, #"route", stopString, #"stop", nil];
[destination setValue:selection1 forKey:#"selection"];
}
}
Make sure that you are NOT connecting the segue to the next view controller to the tableView CELL directly. Connect to the whole UITableViewController / UIViewController (whichever you are using) and give a name, say "segueNameInStoryboard".
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Favorite *favorite = [self.favoriteItems objectAtIndex:indexPath.row];
stopString = favorite.title;
routeString = favorite.subtitle;
/* add this line */
[self performSegueWithIdentifier:#"segueNameInStoryboard" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"segueNameInStoryboard"])
{
UIViewController *nextViewController = segue.destinationViewController;
nextViewController.delegate = self;
NSDictionary *selection1 = [NSDictionary dictionaryWithObjectsAndKeys:routeString, #"route", stopString, #"stop", nil];
nextViewController.selection = selection1;
}
}
So, using storyboard you can create a segue from the UITableViewCell from the first tableViewController to a detailViewController.
Not too complicated, however, when a UISearchBarDisplayController is introduced into the storyboard mix, how can you segue the results cell to the detailViewController?
I am able to search without a problem, I followed this tutorial: http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
All I can do is select a row from the search, it turns blue and doesn't go to the detailViewController.
I have implemented the method prepareForSegue, which works for the non searched cells, but can't figure out this one.
Here's the solution that's based on the comment by #James Chen. Also using a different IndexPath depending on which state the table is in.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toDetail"]) {
Person *person = nil;
if (self.searchDisplayController.active == YES) {
NSIndexPath *indexPath = indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.filteredPersonArray objectAtIndex:indexPath.row];
}
else {
NSIndexPath *indexPath = indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.personArray objectAtIndex:indexPath.row];
}
[[segue destinationViewController] setPerson:person];
}
}
I tried your solution and found that prepareForSegue is called twice
due to the life cycle and didSelect... -> performSegueWithIdentifier.
self:prepareForSegue: object on destination controller is set
(with wrong index) because
dest:viewDidLoad: the destination controller view is loaded after which
self:didSelectRow...: the index is known and properly set.
self:prepareForSegue: object is now correct but has no side effect.
I then focused on didSelect... and came up with this solution where I deleted the segue and pushed the view programmatically:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DestTableViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"DestViewController"];
CustomObj *custObj = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
custObj = [filteredListContent objectAtIndex:indexPath.row];
} else {
storeToDetail = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
controller.custObj = custObj;
[self.navigationController setNavigationBarHidden:NO];
[self.navigationController pushViewController:controller animated:YES];
// presentViewController::animated:completion is always full screen (see problem below)
}
I then experienced some problems going back because I follow a segue
from a mapView, which lead to:
//DestinationViewController
- (IBAction)back:(id)sender
{
[self.navigationController popToRootViewControllerAnimated:YES]; // list
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; // map
}
which is not the way to do it but for now it works.
However, the first part is easy and clean, and maybe it works for you too?!
Ok I think I got it, it seems like a bit of a hack but it works for my purposes:
I am using storyboard:
I have a UITableview controller with UISearchBarDisplayController directly on top of it. No code just drag and drop.
From there, I followed this tutorial to get the search bar to search correctly http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
However prepareForSegue: would only let me display a cell from the original array, not with the search array.
So I used didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (savedSearchTerm) {
searchRowSelected = indexPath.row; //<-- the trick that worked
[self performSegueWithIdentifier:#"ShowDetail" sender:self];
}
}
searchRowSelected is an int variable that I declared at the top of the class.
didSelectRowAtIndexPath: knew which row I was selecting, but prepareForSegue didn't. Thats why I needed that variable.
This is how I used it in prepareForSegue:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"ShowDetail"]) {
dvc = [segue destinationViewController];
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
int row = [path row];
if (savedSearchTerm){ //set the detailViewController with the searched data cell
myDataClass* c = [searchResults objectAtIndex:searchRowSelected];
dvc.myDataClass = c;
}else{ //set the detailViewController with the original data cell
myDataClass* c = [array objectAtIndex:row];
dvc.myDataClass = c;
}
}
}
Also use this code to clean up savedSearchTerm
-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{
[self setSavedSearchTerm:nil];
}
If anyone has a better solution I'm all ears :)