How To Use Storyboard? - iphone

I'm trying to use storyboards segue instead of didSelectRowAtIndex.
This is what I have, but this method does not recognize indexPath.row. Is there an alternative I can use to do the same thing?
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SpecificExerciseTableViewController *upcomingViewController = segue.destinationViewController;
if ([segue.identifier isEqualToString:#"Web"])
{
upcomingViewController.exerciseArray = [[self.muscleArray objectAtIndex:indexPath.row]objectForKey:#"exercises"];
upcomingViewController.muscleName = [[self.muscleArray objectAtIndex:indexPath.row]objectForKey:#"muscleName"];
}
}

Unless you have that indexPath as an ivar, no such variable exists in the scope.
If you would like to get the indexPath for the selected row in a UITableView use:
- (NSIndexPath *)indexPathForSelectedRow
The adjusted code for above:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
SpecificExerciseTableViewController *upcomingViewController = segue.destinationViewController;
if ([segue.identifier isEqualToString:#"Web"])
{
upcomingViewController.exerciseArray = [[self.muscleArray objectAtIndex:indexPath.row]objectForKey:#"exercises"];
upcomingViewController.muscleName = [[self.muscleArray objectAtIndex:indexPath.row]objectForKey:#"muscleName"];
}
}

This trick works fine,heres an example of how I used it to pull parsed elements into a web view
.h file
#property (strong, nonatomic) NSString *url;
#property (strong, nonatomic) UIWebView *webView;
.m file
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if ([segue.identifier isEqualToString:#"WebViewSegue"]) {
WebViewController *webViewController = segue.destinationViewController;
webViewController.url = (self.parseResults)[indexPath.row][#"link"];
webViewController.title = (self.parseResults)[indexPath.row][#"title"];
}
}

Related

[UINavigationController setGoalName:]: unrecognized selector sent to instance 0x7964e2c0

I have created the app with following code. Its working fine with iOS7 but it throws the below error when I run with iOS8.
[UINavigationController setGoalName:]: unrecognized selector sent to instance 0x7964e2c0
My firstViewcontroller.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
GoalDetailsViewController *goalsDetailsViewController = segue.destinationViewController;
NSLog(#"%#",[NSString stringWithFormat:#"%#", [[self.arrCategoryTitle objectAtIndex:indexPath.row] objectAtIndex:indexOfCategory]]);
goalsDetailsViewController.goalName = #"Exercise Daily";
}
My GoalDetailsViewController.h
#interface GoalDetailsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic) NSString *goalName;
Thanks in advance.
Seems like your destinationviewcontroller is a subclass of UINAvigationController.
Try this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
GoalDetailsViewController *goalsDetailsViewController = [(UINavigationController*)segue.destinationViewController topViewController];
NSLog(#"%#",[NSString stringWithFormat:#"%#", [[self.arrCategoryTitle objectAtIndex:indexPath.row] objectAtIndex:indexOfCategory]]);
goalsDetailsViewController.goalName = #"Exercise Daily";
}
The easiest way to handle this crash would be to simply make sure that the destinationViewController is of the type you're expecting before you attempt to set a property on it. Something like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
GoalDetailsViewController *goalsDetailsViewController = segue.destinationViewController;
NSLog(#"%#",[NSString stringWithFormat:#"%#", [[self.arrCategoryTitle objectAtIndex:indexPath.row] objectAtIndex:indexOfCategory]]);
if ([segue.destinationViewController isKindOfClass:[GoalDetailsViewController class]]) {
GoalDetailsViewController *goalsDetailsViewController = segue.destinationViewController;
goalsDetailsViewController.goalName = #"Exercise Daily";
}
}
This change ensures that the destinationViewController is of kind GoalDetailsViewController before treating it as such.

Passing data between two controllers using storyboards

I am trying to pass data from one UITableViewController to another. This is my code in the initial view controller:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Subject *subject = (Subject *)[self.fetchedResultsController objectAtIndexPath:indexPath];
[self showList:subject animated:YES];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)showList:(Subject *)subject animated:(BOOL)animated {
ListsViewController *lists = [[ListsViewController alloc] initWithStyle:UITableViewStyleGrouped];
lists.subject = subject;
NSLog(#"%#", lists.subject);
[self performSegueWithIdentifier:#"showDetail" sender:self];
}
The log output was showing that it had the data I wanted had been passed over. However when I perform the segue and log the subject in the ListsViewController is shows null.
Any ideas?
You need to overwrite prepareForSegue:sender: method. The quick fix would be
- (void)showList:(Subject *)subject animated:(BOOL)animated
{
[self performSegueWithIdentifier:#"showDetail" sender:subject];
}
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetail"]) {
ListsViewController *controller = ([segue.destinationViewController isKindOfClass:[ListsViewController class]]) ? segue.destinationViewController : nil;
controller.subject = ([sender isKindOfClass:[Subject class]]) ? subject : nil;
}
}
The reason why your code did not work is that in your showList:animated: method you created a ListsViewController instance and assigned it a subject, but this view controller was never presented. Instead performSegueWithIdentifier:sender creates another instance of your ListsViewController class which knows nothing about your subject. That's why you need to wait for UIStoryboardSegue to instantiate a destination view controller from the storyboard and then configure it the way you want, which you can do in prepareForSegue:sender: method.
Also it might be not the best idea to use subject as a sender in performSegueWithIdentifier:sender method, because it's just not the sender :). What I would do is create a property subject in your view controller class and use it prepareForSegue:sender:
#interface MyViewController ()
#property (strong, nonatomic) Subject *subject;
#end
#implementation MyViewController
- (void)showList:(Subject *)subject animated:(BOOL)animated
{
self.subject = subject;
[self performSegueWithIdentifier:#"showDetail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetail"]) {
ListsViewController *controller = ([segue.destinationViewController isKindOfClass:[ListsViewController class]]) ? segue.destinationViewController : nil;
controller.subject = self.subject;
}
}
...
#end
Implement prepareForSegue and pass date in this methos
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([seque.identifier isEqualToString:#"showDetail"])
{
ListsViewController *lists = seque.destinationViewController;
lists.subject = subject;
}
}
That's good, but now you need to add this:
First instead of:
[self performSegueWithIdentifier:#"showDetail" sender:self];
You need to send the object:
[self performSegueWithIdentifier:#"showDetail" sender:subject];
Add a property in your ListsViewController.h:
#property (nonatomic, strong) Subject * subjectSegue;
And now in your first view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetail"]) {
ListsViewController * lists = (ListsViewController *)[segue destinationViewController];
lists.subjectSegue = sender;
}
You need to understand that performSegueWithIdentifier:sender: creates a new instance of view controller. So the ListsViewController that you have created is not the being displayed on the screen.
You need to override `prepareForSegue:sender:
- (void)showList:(Subject *)subject animated:(BOOL)animated
{
[self performSegueWithIdentifier:#"showDetail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetail"]) {
ListsViewController *controller = (ListsViewController *)segue.destinationViewController;
controller.subject = self.subject;
}

Accessing text from property from another class

I have tableview with the cells and every cell pushes detailViewController. I want to assign text of the cell to a textLabel in detailViewController.
.h class of masterView
#property (strong,nonatomic) NSString *selectedCellText;
.m class of masterView
#synthesize selectedCellText = _selectedCellText;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedCellText = [[[tableView cellForRowAtIndexPath:indexPath] textLabel] text];
NSLog(#"%#",self.selectedCellText);
}
Here NSLog prints name of the cell
.h of detailViewController
#property (nonatomic, copy) listOfTricksViewController *aReference;
.m of detailViewController
#synthesize aReference = _aReference;
- (void)viewDidLoad
{
[super viewDidLoad];
self.detailViewName.text = self.aReference.selectedCellText;
NSLog(#"%#",self.aReference.selectedCellText);
}
Here NSLog prints null.
Modify your method prepareForSegue like this :
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"detailTrick"])
{
DetailViewController *detailViewController = (DetailViewController *)segue.
NSString *object = nil;
NSIndexPath *indexPath = nil;
indexPath = [self.tableView indexPathForSelectedRow];
// Pass data
detailViewController.aString = self.cellObjects[indexPath.row];
}
}
You need to call your DetailViewController and forward the data to this controller (supposing here you have a #property aString in your header of DetailViewController)
.h of detailViewController
#property (nonatomic, strong) NSString *aString;
.m of detailViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.detailViewName.text = self.aString;
NSLog(#"%#",self.aString);
}

UITableViewController unrecognized selector sent to instance

I have a tableviewcontroller and a detailtableviewcontroller when I pass an integer I get
-[UITableViewController setSurveyNumber:]: unrecognized selector sent to instance
Bizard thing is exact same code works for tableviewcontroller to -> uiviewcontroller
table -> table code
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"pushSurveyDetails"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSInteger row = [indexPath row];
SurveyDetailViewController *surveyController = [segue destinationViewController];
surveyController.surveyNumber=row;
}
}
in SurveyDetailViewController.h
#interface SurveyDetailViewController : UITableViewController
{
}
#property int surveyNumber;
#end
SurveyDetailViewController.m
#implementation SurveyDetailViewController
#synthesize surveyNumber;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Survey Number is %i",surveyNumber);
}
why this error occurs?
The error message indicates that [segue destinationViewController] returns a UITableViewController and not a SurveyDetailViewController as expected.
The controller class can be set in the storyboard file.

DetailView shows only one entry of Tableview

I've got a Master-Detail Applicaton in Xcode with a TableView and a SearchDisplayController.
In the TableView I have got a NSArray with 10 entries.
If I use the Searchbar, the DetailView shows correctly the entry I clicked on.
But if I do not use the Searchbar and click in the TableView on an entry, the DetailView every time shows me the first entry of the TableView.
What can I do to fix it?
MasterViewController.m: http://i.imgur.com/ZS1Oe.png
MasterViewController.h:
#import <UIKit/UIKit.h>
#interface DPMasterViewController : UITableViewController
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#end
DetailViewController.m: http://i.imgur.com/AkVJ8.png
DetailViewController.h:
#import <UIKit/UIKit.h>
#interface DPDetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
Sorry that I use pictures, but I think it is easier for you to check. :)
I hope you can help me!
If anything is missing, just tell me.
EDIT:
In This Method after the else every time the indexPath.row = 0. I don't know how to fix it :(
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetail"]) {
DPDetailViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
destViewController.detailItem = [searchItemList objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
destViewController.detailItem = [itemList objectAtIndex:indexPath.row];
}
}
}
It looks like you are not performing any actions when you click on a cell of the tableView that is not part of the searchDisplayController, so try to change your tableView:didSelectRowAtIndexPath: method to
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"showDetail" sender:self];
}