I'm trying to push data to a detail view. I'm able to push to the new view but the object equals null.
ProfileDetailView.h
#property (nonatomic, strong) PFObject *user;
#property (weak, nonatomic) IBOutlet UILabel *username;
#property (weak, nonatomic) IBOutlet UILabel *bio;
#property (weak, nonatomic) IBOutlet UILabel *name;
TableViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
PFObject *object = [self.objects objectAtIndex:indexPath.row];
ProfileDetialView *controller = [[ProfileDetialView alloc]initWithNibName:#"ProfileDetialView" bundle:Nil];
controller.user = object;
//NSLog(#"%#",controller.user);
[self performSegueWithIdentifier: #"ShowDetails" sender: self];
}
I've tried doing this multiple ways but ether it won't push to new view or it wont pass the object to the new view. It's probably something stupid as usually but any suggestions would be appreciated!
You should use prepareForSegue.
Assume ShowDetails segue goes to ProfileDetailView (and it is a controller) (am I right?).
you should add into TableViewController
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"ShowDetails"]) {
ProfileDetailView *detailController = segue.destinationViewController;
detailController.user = (PFObject *) sender;
}
}
and change :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
PFObject *userObject = [self.objects objectAtIndex:indexPath.row];
[self performSegueWithIdentifier: #"ShowDetails" sender: userObject];
}
You code doesn't work, because you instantiate NEW detail controller, add data to it, but segue opens ANOTHER instance of detail controller (where you have no data).
try into prepareForSegue method, and in the performSegue in sender object
[self performSegueWithIdentifier: #"ShowDetails" sender: object];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowDetails"]) {
ProfileDetialView *controller = (ProfileDetialView *)segue.destinationViewController;
PFObject *object = (PFObject *)sender;
controller.user = object;
}
}
hope it works for you
Related
I want to pass a NSInteger from a tableViewController (HistoryTableViewController) to another viewController (InformationViewController) but apparently it is not responding to my selector.
HistoryTableViewController.h:
#class HistoryTableViewController;
#protocol HistoryTableViewControllerDelegate <NSObject>
- (void)addItemViewController:(HistoryTableViewController *)controller passItem:(NSInteger *)rowNum;
#end
#interface HistoryTableViewController : UITableViewController {
NSInteger row;
}
#property (nonatomic, weak) id <HistoryTableViewControllerDelegate> delegate;
#end
HistoryTableViewController.h
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
row = [self.tableView indexPathForSelectedRow].row;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"informationSegue"]) {
if([self.delegate respondsToSelector:#selector(addItemViewController:passItem:)]){
[self.delegate addItemViewController:self passItem:&(row)];
}
}
}
InformationViewController.h:
#interface InformationViewController : UIViewController <HistoryTableViewControllerDelegate>
#property (nonatomic, assign) NSInteger rowIn;
InformationViewController.m
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"informationSegue"]) {
HistoryTableViewController *historyvc = segue.destinationViewController;
historyvc.delegate = self;
}
}
- (void) addItemViewController:(HistoryTableViewController *)controller passItem:(NSInteger *)rowNum {
rowIn = *rowNum;
}
"informationSegue" is my segueIdentifier to go from HistoryTableViewController to InformationViewController.
I actually found out the answer myself. I was using the code for passing the delegate back to another view controller, but I was supposed to pass the delegate forward between view controllers
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.data= [self.nameList objectAtIndex:indexPath.row];
self.data= [self.rollList objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"DetailVC" sender:self];
}
I've displayed student's name and roll number in custom cell. Now when i select one row i would like to pass those data to another UIViewController and display in labels. For I've one NSObject type file called 'Name' and i've one variable called 'data' which is of type 'Name'. Now here's my code in didSelectRowAtIndexPath where the nameList is overlapped by rollList which are stored on same variable self.data. if rollList line is removed then it works good. But when I store rollList in self.data it will overlap other.
Where, self.nameList is variable of type NSMutableArray which contains name of student and similarly, self.rollList contains student's roll.
Below is the code to pass data from segue. Here DetailVC is the destinationViewController, vc.data is the variable of type 'Name' and self.data is also the variable of same type.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"DetailVC"]){
DetailVC *vc = (DetailVC *) segue.destinationViewController;
vc.data = self.data;
}
}
Overlapping is fundamental thing.
In your case your in NSObject type file (Name) you have to add two variable
NSNumber *rollNo;
NSString *name;
After that
-- UPDATE --
#interface TableVC : UIViewController {
Name *data;
}
-(void)viewDidLoad {
data = [[Name alloc] init]
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.data.name = [self.nameList objectAtIndex:indexPath.row];
self.data.rollNo = [self.rollList objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"DetailVC" sender:self];
}
Then
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"DetailVC"]){
DetailVC *vc = (DetailVC *) segue.destinationViewController;
vc.data = self.data;
}
}
------ Detail VC ---
#property (nonatomic, strong) Name *data;
-(void)viewDidLoad {
self.labelRollNo.text = self.data.rollNo;
self.labelName.text = self.data.name;
}
try this way
#interface ViewController ()
{
NSString *name;
NSString *roll;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
name= [self.nameList objectAtIndex:indexPath.row];
roll= [self.rollList objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"DetailVC" sender:self];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"DetailVC"]){
DetailVC *vc = (DetailVC *) segue.destinationViewController;
vc.name = name;
vc.roll = roll;
}
}
you create two NSString name and roll properties in your DetailVC
DetailVC.h
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *roll;
I have tried all the ways to pass this data between the view Controllers, both of which are modally represented as page sheet.
in ViewController 1 .h
——————————
#property (strong, nonatomic) NSMutableDictionary * updatableProduct ;
//#property (strong, nonatomic) NSDictionary * updatableProduct ; //tried
in ViewController 1 .m
——————————
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * cellIdentifier = #"Cell";
TailorOUCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.updateOrder.tag = indexPath.row;
[cell.updateOrder addTarget:self action:#selector(nowUpdateOrder:) forControlEvents:UIControlEventTouchUpInside];
orderToUpdate = [orderQueryResults objectAtIndex:indexPath.row];
return cell;
}
-(void)nowUpdateOrder:(id)sender{
UIButton *senderButton = (UIButton *)sender;
updatableProduct = [orderQueryResults objectAtIndex:(long)senderButton.tag];
[self performSegueWithIdentifier:#"updateOrder" sender:updatableProduct];
//[self performSegueWithIdentifier:#"updateOrder" sender:self]; //tried
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"updateOrder"]) {
OUEditView * ouv = (OUEditView *)segue.destinationViewController;
ouv.orderDetails = updatableProduct;
[segue.destinationViewController setModalPresentationStyle:UIModalPresentationPageSheet];
}
}
in ViewController 2 .h
——————————
#property (strong, nonatomic) NSMutableDictionary * orderDetails ;
in ViewController 2 .m
——————————
#synthesize orderDetails;
But the orderDetails = null in log
Any Help!
You need to add breakpoints or log statements to your code and see what's happening.
Is prepareForSegue being called at all?
Is the IF statement matching the identifier?
Is the value in "updatableProduct" not nil?
Are you checking the value of ouv.orderDetails in viewDidLoad or
viewWillAppear, instead of in the init method? (The init method fires
before prepareForSegue is called.)
I have a table view controller segueing (with identifier feedToPollQuerySeg) to another view controller.
I am trying to print out the index number of the row selected in a label in the latter.
Feed View:
#interface FeedController3 : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, weak) IBOutlet UITableView* feedTableView;
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(NSString*)stringNum{
if([segue.identifier isEqualToString:#"feedToPollQuerySeg"]){
PollQueryController *pqc = [[PollQueryController alloc] init];
pqc = [segue destinationViewController];
NSLog(#"This is row sending: %#", stringNum);
pqc.parentRowSelected.text = stringNum;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger rowSelected = indexPath.row;
NSString *stringNum = [NSString stringWithFormat:#"%d", rowSelected];
NSLog(#"This is row selected: %#", stringNum);
[self performSegueWithIdentifier: #"feedToPollQuerySeg" sender: stringNum];
}
PollQuery View
#interface PollQueryController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UILabel *parentRowSelected;
#implementation PollQueryController
#synthesize parentRowSelected;
-(void)viewDidLoad{
[super viewDidLoad];
NSLog(#"Parent Row Selected: %#", parentRowString);
...
}
But the label isn't updating...?
This is row selected: 1
This is row sending: 1
Parent Row Selected:
Its because when you are in prepareForSegue of FeedController3, PollQueryController's view isn't initialized.
Add NSString in PollQueryController set NSString value in prepareForSegue.
In viewWillAppear of PollQueryController assign text to parentRowSelected label.
Like This -
In the viewController that will present the another viewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqual:#"feedToPollQuerySeg"])
{
PollQueryController *pvc = [segue destinationViewController];
pvc.myString = stringNum;
}
}
And inside the presented viewController:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.parentRowSelected.text = self.myString;
}
Here is a neater way to achieve what you want:
FeedController3.m:
#interface FeedController3
#property (nonatomic) int rowSelected;
#end
#implementation
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.rowSelected = indexPath.row;
NSLog(#"This is row selected: %#", [NSString stringWithFormat:#"%d", self.rowSelected]);
[self performSegueWithIdentifier:#"feedToPollQuerySeg" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"feedToPollQuerySeg"])
{
// Get reference to the destination view controller
PollQueryController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
vc.rowSelected = self.rowSelected;
}
}
#end
PollQueryController.h:
#interface PollQueryController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic) int rowSelected;
#property (weak, nonatomic) IBOutlet UILabel *parentRowSelected;
#end
PollQueryController.m:
#implementation
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.parentRowSelected.text = [NSString stringWithFormat:#"%d", self.rowSelected];
}
#end
My app have UITableViewController and DetailViewController.
UITableViewController with multi cell selection and Detail accessory button.
If the user select multiple cell and tap on TOTAL Button Alert message show the total of courses price.
And if user tap on Detail accessory button it Segue to DetailViewController.
OK now my problem is how could I do that with my code:
UITableViewController.m
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[object valueForKey:#"courseCode"] description];
cell.detailTextLabel.text = [[object valueForKey:#"courseName"] description];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[[segue destinationViewController] setDetailItem:object];
}
}
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([[[object valueForKey:#"creditHours"] description]isEqualToString: #""]) {
}
//some thing doing if the user deselect the cell..
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([[[object valueForKey:#"creditHours"] description]isEqualToString: #""]) {
}
//some thing doing if the user deselect the cell..
}
- (IBAction)doneButton:(id)sender {
given the total...
}
DetailViewController.h
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UITextField *courseCodeLabel;
#property (weak, nonatomic) IBOutlet UITextField *courseNameLabel;
#property (weak, nonatomic) IBOutlet UITextField *creditHoursLabel;
#property (weak, nonatomic) IBOutlet UITextField *preRequisitesLabel;
#property (weak, nonatomic) IBOutlet UITextField *coursePriceLabel;
#property (weak, nonatomic) IBOutlet UITextField *courseEPPLabel;
#property (weak, nonatomic) IBOutlet UITextView *courseDetailLabel;
DetailViewController.m
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
#synthesize detailItem = _detailItem;
#synthesize courseCodeLabel = _courseCodeLabel;
#synthesize courseNameLabel = _courseNameLabel;
#synthesize creditHoursLabel = _creditHoursLabel;
#synthesize preRequisitesLabel = _preRequisitesLabel;
#synthesize coursePriceLabel = _coursePriceLabel;
#synthesize courseEPPLabel = _courseEPPLabel;
#synthesize courseDetailLabel = _courseDetailLabel;
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
[self configureView];
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.courseCodeLabel.text = [[self.detailItem valueForKey:#"courseCode"] description];
self.courseNameLabel.text = [[self.detailItem valueForKey:#"courseName"] description];
self.creditHoursLabel.text = [[self.detailItem valueForKey:#"creditHours"] description];
self.preRequisitesLabel.text = [[self.detailItem valueForKey:#"preRequisites"] description];
self.coursePriceLabel.text = [[self.detailItem valueForKey:#"coursePrice"] description];
self.courseEPPLabel.text = [[self.detailItem valueForKey:#"courseEPP"] description];
self.courseDetailLabel.text = [[self.detailItem valueForKey:#"courseDetails"] description];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
Notice that the segue working good in the normal way.
I think currently your segue links a tableview cell (that prototype) with your detail controller. You can try instead link the tableview controller itself (i.e. the entire thing) with your detail controller. (just ctrl drag from the bottom of your tableview controller to do that)
Then you handle your -prepareForSegue method as usual, but you will need to call -performSegue to actually trigger the segue. Tapping on the cell will have no effect. So in your -tableView:tableViewaccessory.... method you can call performSegue to do your navigation, and handle your didSelectRow.. method as you wish.