I am new to programming and am probably hung up on a simple problem. I am using parse for my array in my tableview. When the row is selected i want to segue to a search bar on another view controller. The segue works fine and the tableview works fine but i can't seem to get the objectId to pass.
#import "bookmarkViewController.h"
#import "Parse/Parse.h"
#import <ParseUI/ParseUI.h>
#import "ViewController.h"
#implementation bookmarkViewController
#synthesize postArray;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self
action:#selector(refreshButtonHandler:)]];
}
- (void)viewWillAppear:(BOOL)animated
{
if ([PFUser currentUser])
[self refreshButtonHandler:nil];
}
#pragma mark - Button handlers
- (void)refreshButtonHandler:(id)sender
{
//Create query for all Post object by the current user
PFQuery *postQuery = [PFQuery queryWithClassName:#"Post"];
[postQuery whereKey:#"author" equalTo:[PFUser currentUser]];
// Run the query
[postQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
//Save results and update the table
postArray = objects;
[self.tableView reloadData];
}
}];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section
{
// Return the number of rows in the section.
return postArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell with the textContent of the Post as the cell's text label
PFObject *post = [postArray objectAtIndex:indexPath.row];
[cell.textLabel setText:[post objectForKey:#"textContent"]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath{
NSLog(#"cell tapped");
PFObject *post = [postArray objectAtIndex:indexPath.row];
NSLog(#"%#", post.objectId);
[self performSegueWithIdentifier:#"searchBookmark" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewController *vc = [segue destinationViewController];
vc.labelText = post.objectId;
}
}
#end
at vc.label.text i always get use of undeclared identifier "post" but i can't seem to figure out how to get it recognized. It is in the above method.
the NSLogs reply correctly 16:17:27.513 [App] cell tapped
[App] cgdVY7Eu9h
Change your didSelectRowAtIndexPath and prepareForSegue to this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath* )indexPath{
[self performSegueWithIdentifier:#"searchBookmark" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"cell tapped");
PFObject *post = [postArray objectAtIndex:indexPath.row];
NSLog(#"%#", post.objectId);
ViewController *vc = [segue destinationViewController];
vc.labelText = post.objectId;
}
}
Post is a local variable that you created inside didSelectRowAtIndexPath, so it can't be used outside that method. The easy way to fix this, is to pass post as the sender argument in performSegueWithIdentifier:sender:. You can pass any object you want as the sender.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
NSLog(#"cell tapped");
PFObject *post = [postArray objectAtIndex:indexPath.row];
NSLog(#"%#", post.objectId);
[self performSegueWithIdentifier:#"searchBookmark" sender:post];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
PFObject *post = (PFObject *)sender;
ViewController *vc = [segue destinationViewController];
vc.labelText = post.objectId;
}
UIViewController -> segue -> UITableViewController
I had one problem that i solved with answer -1- Thanks.
So i had a kind of UIViewController and i wanted with button just segue to another UITableViewController and i noticed that it stacked and was frozen. I could not scroll my Table ...
My Code was :
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
MasterViewController *controller =segue.destinationViewController;
controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:controller animated:YES completion:nil];
}
My CPU was over 100% overloaded.
So the answer number 1 worked for me well. New Code is then :
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
MasterViewController *vc = [segue destinationViewController];
}
and the table with 30 entries works now just like a charm =)
Related
I have a TableView that load JSON content from web.
I use AFNetworking and JSONModel. And I use this tutorial do Receive and Parse the Data
Here is the code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"CellIdentifier";
__weak ProgramacaoTableCell *cell = (ProgramacaoTableCell *)[self.tableView dequeueReusableCellWithIdentifier:identifier];
ProgramacaoModel* programacao = _programacao.programacaoArray[indexPath.row];
// NameLabel is the Label in the Cell.
cell.nameLabel.text = [NSString stringWithFormat:#"%#", programacao.atracao ];
return cell;
}
I want to know how pass this data to a Detail ViewController.
In my DetailViewController i have the properties to receive the data.
#property (nonatomic, strong) IBOutlet UILabel *programacaoNomeLabel;
You can access to your controller through your navigation:
NSArray* vcStack=[self appDelegate].myNavigationController.viewControllers;
UIViewController* vcUnder;
if(vcStack.count > 0)
vcUnder=[vcStack objectAtIndex:(vcStack.count-1)];
// -1 depends when you called your controller that's why we test the kind of class
if([vcUnder isKindOfClass:[DetailViewController class]]){
((DetailViewController*) vcUnder). programacaoNomeLabel = #"some data";
}
I find the answer
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Pass the selected object to the new view controller.
if ([[segue identifier] isEqualToString:#"pushDetalhesView"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
// Pega o objeto da linha selecionada
ProgramacaoModel *object = [_programacao.programacaoArray objectAtIndex:indexPath.row];
// Pass the content from object to destinationViewController
[[segue destinationViewController] getProgramacao:object];
}
}
In my Details ViewController I create an iVar
#interface ProgramacaoDetalhesViewController ()
{
ProgramacaoModel *_programacao;
}
And set two method, one to receive the content and another to set the Labels
- (void) getProgramacao:(id)programacaoObject;
{
_programacao = programacaoObject;
}
- (void) setLabels
{
programacaoNomeLabel.text = _programacao.atracao;
}
I am trying to go from a UITableView with prototype cells to a detailviewcontroller of the item I selected on.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"historyToDetail"])
{
BYFHistoryDetailViewController *controller = (BYFHistoryDetailViewController *)segue.destinationViewController;
controller.workOut = [[BYFWorkOut alloc] init];
controller.workOut=_selectRow;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BYFHistoryTableViewController *detailViewController =[[BYFHistoryTableViewController alloc] init];
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
BYFWorkOut *selectedItem = items[indexPath.row];
_selectRow = selectedItem;
}
What is not happening is the transition from the table to detail I have a push segue from the prototype cell to the details.
What am I missing?
You are doing quite a lot wrong here. When using segue's you don't create an instance of the class. You simply call:
[self performSegueWithIdentifier:#"MySegue" sender:self];
This will use the segue you have defined in the storyboard. Where MySegue is the segue ID you created.
When you want to pass in data you use the callback
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
BYFHistoryDetailViewController *vc = (BYFHistoryDetailViewController *)[segue destinationViewController];
vc.workOut = selectedItem;
}
But using this callback will mean you will need to store selectedItem somewhere after you click the row so you can access it here.
EDIT
Your code seems a bit odd here also.
You set workout to a new object.
detailViewController.workOut = [[BYFWorkOut alloc]init];
Create another object from data.
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
BYFWorkOut *selectedItem = items[indexPath.row];
And then assign the new object, overwriting the previous one.
//give detail view controller a pointer to the item object in row
detailViewController.workOut = selectedItem;
There is no need to have the first line of code at all
EDIT 2
If you only going to be using the one selected item at a time. you can do this in your UITableViewController class.
#implementation MyTableViewControllerClass
{
BYFWorkOut *_selectedItem;
}
inside didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
_selectedItem = items[indexPath.row];
}
EDIT 3
I've modified the code you posted here. You didn't add the first line of code i posted. Please look at this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"historyToDetail"])
{
BYFHistoryDetailViewController *controller = (BYFHistoryDetailViewController *)segue.destinationViewController;
controller.workOut = _selectRow;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *items = [[BYFworkOutStore sharedStore] allItems];
_selectRow = items[indexPath.row];
[self performSegueWithIdentifier:#"historyToDetail" sender:self];
}
You need to name your segue and call the method:
[self performSegueWithIdentifier:#"MySegue" sender:self];
hi I'm developing a iOS which featuring image updates. For using the NSURLConnectionDelegate and setDatasource to bring the image to tableview with help of php and json now I'm trying give a detail view option for the my table view going as tough time in this can please help me.
the setdatasource coding the imagecell.m
-(void)setDataSource:(image *)inImageObj
{
self.decriptionLabel.text = inImageObj.desp;
NSURL *url = [NSURL URLWithString:inImageObj.img];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
self.responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
{
[self.responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
{
UIImage *image = [UIImage imageWithData:self.responseData];
self.thumbImageView.image = image;
}
this is code I used for view the images in table view.m
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *cellIdentifier =#"Cell";
imgpoliticalCell *cell =(imgpoliticalCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell== nil) {
cell = [[imgpoliticalCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
[cell setDataSource:[imgevery objectAtIndex:indexPath.row]];
return cell;
}
now I want view the image and description in the detailviewcontroller. I tried with segue i not able to get it properly
detailviewcontroller.h file
#interface DetailpoliticalViewController : UIViewController
#property (strong,nonatomic) UIImage * image;
#property (strong,nonatomic) NSString * data;
#property (strong, nonatomic) IBOutlet UIImageView *imageview;
#property (strong, nonatomic) IBOutlet UILabel *view;
this is code I have used in the detailviewcontroller.m file
#implementation DetailpoliticalViewController
#synthesize imageview,view;
#synthesize image,data;
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageview.image = self.image;
self.view.text= self.data;
// Do any additional setup after loading the view.
}
And this is the push segue code which I have used in the table view controller
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Detailsegue"]) {
DetailpoliticalViewController *detailvc =(DetailpoliticalViewController *)segue.destinationViewController;
NSIndexPath *indexPath =[self.mytableview indexPathForCell:(UITableViewCell *) sender];
image * eve = [imgevery objectAtIndex:indexPath.row];
[detailvc setDataSource:[imgevery objectAtIndex:indexPath.row]];
}
Now I'm not able to view the image and description in my detail view controller I'm getting the nil exception error
please can any one suggest some way to view the details
thanks in advance
Use
NSIndexPath *indexPath =[self.mytableview indexPathForSelectedRow];
instead of
NSIndexPath *indexPath =[self.mytableview indexPathForCell:(UITableViewCell *) sender];
check this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier: #"DetailSegue" sender: self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"DetailSegue"]) {
DetailpoliticalViewController *detailvc =(DetailpoliticalViewController *)segue.destinationViewController;
indexPath = [self.tableView indexPathForSelectedRow];
image * eve = [imgevery objectAtIndex:indexPath.row];
[detailvc setDataSource:[imgevery objectAtIndex:indexPath.row]];
}
}
Check this tutorial LINK 1
You can do this by implementing this two method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"Detailsegue" sender:indexPath];
}
and below method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Detailsegue"]) {
DetailpoliticalViewController *detailvc =(DetailpoliticalViewController *)segue.destinationViewController;
NSIndexPath *indexPath = (NSIndexPath *)sender;
image * eve = [imgevery objectAtIndex:indexPath.row];
[detailvc setDataSource:[imgevery objectAtIndex:indexPath.row]];
}
}
I have two VCs and i want to pass resourceName from HomeViewController to SingleWebViewController. But the resourceName is getting null.
HomeViewController.m
#import "HomeViewController.h"
#import "SingleWebViewController.h"
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
singleWebViewController = segue.destinationViewController;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = indexPath.row;
switch (selectedRow)
{
case 0:
{
singleWebViewController.resourceName=#"intro";
NSLog(#"HtmlFileName:%#" , singleWebViewController.resourceName);
[self performSegueWithIdentifier:#"toSingleWebView" sender:self];
break;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
SingleWebViewController.h has the following line
#property (nonatomic,strong)NSString *resourceName;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:self.resourceName ofType:#"html" inDirectory:nil] ;
NSLog(#"%#se:" , self.resourceName);
NSURL *url = [NSURL fileURLWithPath:htmlFile ];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
_webView.delegate=(id)self;
}
i did notice that didSelectRowAtIndexPath is getting called before prepareForSegue. what's the cause for this. Please suggest.
In prepareForSegue, you're assigning something new to singleWebViewController. If this controller is different from the controller that's already assigned in tableView: didSelectRowAtIndexPath:, which I assume it is, then your property will be reset.
Instead, do this:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
singleWebViewController = segue.destinationViewController;
singleWebViewController.resourceName = #"intro";
}
In your prepareForSegue you can set the property resourceName
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SingleWebViewController *singleWebViewController = segue.destinationViewController;
[singleWebViewController setResourceName:#"Resource name"];
}
try this..pass value in prepareforsegue
Edit: if you want for different case to pass the different value then do this..i m assuming you want to segueway to same ViewController ie SingleWebViewController here.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toSingleWebView"]) {
SingleWebViewController *singleWebViewController = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathOfSelectedRow];
if(indexpath.row == 0){
singleWebViewController.resourceName=#"intro";
}
else if(indexPath.row == 1){
singleWebViewController.resourceName=#"some other value";
}
else{
singleWebViewController.resourceName=#"something else";
}
NSLog(#"HtmlFileName:%#" , singleWebViewController.resourceName);
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = indexPath.row;
switch (selectedRow)
{
case 0:
{
[self performSegueWithIdentifier:#"toSingleWebView" sender:self];
break;
}
case 1:
{
[self performSegueWithIdentifier:#"toSingleWebView" sender:self];
break;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
You're setting resourceName after viewDidLoad has been called. Add a custom initialiser, initWithResourceName:(NSString *)resourceName, and set it there. Or move the code from viewDidLoad to viewDidAppear:.
Try with:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
HomeViewController *obj = segue.destinationViewController;
if([segue.identifier isEqualToString:#"toSingleWebView"]){
obj.singleWebViewController = singleWebViewController;
}
}
I am just trying to transfer a simple string from a UILabel in a prototype cell into a label in the next View Controller. Value of label.text in the viewDidLoad of the View Controller is returning (null).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
mainCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (mainCell == nil) {
mainCell = [[dictionaryTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString* date = [dateArray objectAtIndex:indexPath.row];
mainCell.viewLabel.text = date;
return mainCell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
ViewController *one = segue.destinationViewController;
one.label.text = mainCell.viewLabel.text;
}
}
What am I doing wrong here?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *one = segue.destinationViewController;
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
}
And actually, assigning text to text label you should do in your viewController one's method(viewDidLoad or viewWillAppear). So, you need to make a property in viewController one for transferring NSString.
You can use indexPathForSelectedRow:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
ViewController *one = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Or you can also use sender if your segue is from the cell to the next scene, e.g.:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"View Segue"])
{
ViewController *one = segue.destinationViewController;
NSAssert([sender isKindOfClass:[UITableViewCell class]], #"Not cell");
UITableViewCell *cell = sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Two things to note:
As a matter of good programming style, I am not retrieving the text value from the cell. I'm retrieving the text value from the model. You should not be relying upon the view for information to be passed along. Go back to the model, the original source of the information.
Do not set the text property of the label in the destination controller directly. The controls of the destinationController have not been created yet. You should defer setting controls until the destinationController's viewDidLoad. So, instead, create a NSString property in the destination controller:
#property (nonatomic, strong) NSString *textProperty;
Clearly, you should use a more descriptive name than textProperty, but hopefully you get the idea. Anyway, prepareForSegue can set this new property and the viewDidLoad of the destination controller should then use that NSString property to populate the text property of the UILabel, e.g.:
- (void)viewDidLoad
{
[super viewDidLoad];
self.label.text = self.textProperty;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
YourViewController *controller =[[YourViewController alloc] init];
[self presentModalViewController:controller animated:YES];
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
Change the label.text after presentModalViewController. Now what happens?
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
I understand you are already using Segue. You should follow the other answer.