Prepare for segue crashing at isKindOfClass comparison - ios

My prepare for segue call keeps causing a crash without any error message. So I use NSLog to track what’s happening. The following line is never reached
NSLog(#"The VCs matched!!: " )
Here is the method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"enter prepare for segue.");
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
if ([segue.identifier isEqualToString:SegueIdentifierA]) {
NSLog(#"Destination to match are: %#, %# .",segue.destinationViewController,[PaperDetailViewController class] );
if ([segue.destinationViewController isKindOfClass:[PaperDetailViewController class]]) {
NSLog(#"The VCs matched!!: " );
PaperDetailViewController *paperDetailView = (PaperDetailViewController *)segue.destinationViewController;
}else NSLog(#"NO ONO NO match for %# AND %#.",segue.destinationViewController,[PaperDetailViewController class] );
}
NSLog(#"exit prepare for segue.");
}

It would be great to see the stack trace as the comments suggest. That would provide valuable clues. Without them, the most likely culprit is:
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
Which is blindly assuming that the sender is a UITableViewCell. If it isn't, you'd see a crash for sure (and we'd see it in the stack trace). If a table selection is what's triggering the segue, than this is safer and easier to read...
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];

Given the information all I can recommend is that you specify the class for your view controller in the storyboard editor.

Sorry for the false alarm. There seems to have been a problem with my Xcode. Xcode just crashed and after I restarted it, everything just work as expected. Thanks and +1 to everyone for helping.

Related

get tableView of a UISearchBar

I have an UISearchBar in on top of my TVC. If the search is active it displays another tableView on top of the normal tableView (this is normal). Now i need to get the "searchTableView" in prepareForSegue() because I need to call:
var newIndexPath = table.indexPathForSelectedRow!
and this fails if you search something.
I also can't do the decision in didSelectRowAtIndexPath() because the segue is called to fast because it is 'linked' directly to the UITableViewCell. I also tried to create the segue from the ViewController but this also fails because the segue needs to end on the same ViewController again.
So basically I want to ask if anyone knows how to solve the error in the Code line above will doing a search.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath;
if (self.searchDisplayController.active)
{
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
}
else
{
indexPath = [self.tableView indexPathForSelectedRow];
}
// Use the indexPath...
}

Segue With NSUserDefaults + NSCoder Object

- (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.

IOS programming: Passing large arrays over segues, good or bad idea?

I am relatively new to IOS development and throughout my application I have been passing a lot of information between my view controller segues. I am currently getting this data from a cloud database and I am worried as time goes on the data I will be passing over my segues will increase as the cloud data increases. Is it a bad idea to pass large amounts of data over these segues, how will it affect the performance of my application if I will eventually pass relatively large arrays over these segues (1,000 to 2,000 elements)? What else can I do if this is a bad idea? Suggestions, tips, pointers would all be great. Thank You
As long as you are just passing the pointer to strong/retaining property this will not have a negative effect on the performance — just a pointer is set, it doesnt matter how the object looks like.
Assume this code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"otherSegue"]) {
OtherViewController *destViewController = segue.destinationViewController;
destViewController.dataArray = self.downloadedArray;
}
}
As long as the property dataArray on otherViewController is strong or retaining (#property (strong) NSArray *dataArray;), the execution time of that code should not increase with the size of the array, as just a pointer is passed.
I don't really use storyboards, but a quick look on google pointed to something:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
}
}

How to obtain data passed in performSegueWithIdentifier

This will probably take two seconds to answer, but my search skills have not gotten me very far on this issue. I am performing a segue but I'm not sure how to grab the id on the destination. Here is my code on the tableview controller.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath: NSIndexPath *)indexPath{
NSLog(#"reaching accessoryButtonTappedForRowWithIndexPath:");
[self performSegueWithIdentifier:#"leads_calls_to_detail" sender:[[self.leads_calls objectAtIndex:indexPath.row] objectForKey:#"ID"]];
}
What do I have to create on my destination view controller to be able to grab the id that I'm attempting to pass, or is the way I'm performing my segue incompatible with what I am attempting?
You should just pass values to the destinationViewController inside prepareForSegue: and pass self as the sender.. try using something like:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"leads_calls_to_detail"])
{
YourViewController *controller=(YourViewController *)segue.destinationViewController;
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
//Or rather just save the indexPath in a property in your currentViewController when you get the accessoryButtonTappedForRowAtIndexPath callback, and use it here
controller.yourPropertyToSet = [self.leads_calls objectAtIndex:path.row];
}
}
And also according to Rob Mayoff, you can grab the index path for the row that the accessory was tapped at by using something like this:
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];//where sender is the sender passed in from prepareForSegue:
How to find indexPath for tapped accessory button in tableView

UITableView only sending data to Detail View Controller on Second Try

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;
}
}

Resources