How do I pass an attribute (this attribute is from an entity) via prepareForSegue for a custom cell?
Consequently, I also have doubts about sending this attribute as filter through in accordance with the line that the user clicks? For example, in the first table the user clicks in the "Pizzeria", then the second screen is shown another table containing only establishments with the category "Pizzeria".
Here is my code so far
#pragma mark - Ações da tabela
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//O número de linhas da tabela será o mesmo número de objetos na lista de categorias
return listaDeCategorias.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CelulaEstabelecimentoTableViewCell *celula = [tableView dequeueReusableCellWithIdentifier:IdentificadorCelula
forIndexPath:indexPath];
if(!celula) {
celula = [[CelulaEstabelecimentoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:IdentificadorCelula];
}
categoria = [NSEntityDescription insertNewObjectForEntityForName:#"Categoria" inManagedObjectContext:contexto];
categoria.nome = [listaDeCategorias objectAtIndex:indexPath.row];
[celula.textLabel setText:categoria.nome];
[celula setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return celula;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
categoria.nome = [listaDeCategorias objectAtIndex:indexPath.row];
//NSString *categoriaClicada = [listaDeCategorias objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:IdentificadorSegue sender:categoria.nome];
}
#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:IdentificadorSegue]) {
UINavigationController *navigationController = [segue destinationViewController];
EstabelecimentoViewController *destino = (EstabelecimentoViewController *)([navigationController viewControllers][0]);
}
}
Note: The prepareForSegue method is purposely incomplete because they do not know how to proceed from there.
And here the custom cell I wish fill with filtered data
Mapped by:
Storyboard:
Assuming the ViewController you are segueing too is EstabelecimentoViewController which has a public property "nome", this is how you would pass "nome" to EstabelecimentoViewController.nome:
#import 'EstabelecimentoViewController.h'
.
.
.
#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:IdentificadorSegue]) {
EstabelecimentoViewController *establishmentVC = [segue destinationViewController];
establishmentVC.nome = categoria.nome;
}
}
/* Try This...*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"mySegue"] && self.demoObject != nil) {
// This line returns a value...
NSLog(#"self.demoObject = %#", self.demoObject.itemDescription);
// ...but it crashes here when it tries to set on the destinationViewController
if ([[segue destinationViewController] isKindOfClass:[SecondViewController class]]) {
SecondViewController *destinationViewController = (SecondViewController *)[segue destinationViewController];
destinationViewController.selectedItemPhoto = self.demoObject.photo;
destinationViewController.selectedItemTitle = self.demoObject.itemDescription;
}
}
}
Related
when I come the part of sending image from UICollectionViewController to another ViewController here is View A:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Detail Segue"])
{
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
NSIndexPath *path = [[self.collectionView indexPathsForSelectedItems] lastObject];
Photo *selectedPhoto = self.photos[path.row];
PhotoDetailVC.photo = selectedPhoto;
}
}
and I receive it in the ViewController (View B) using:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.imageView.image= self.photo.image;
}
I think the problem is that you didn't call performSegueWithIdentifier:sender: in any place in code which actually responsible for triggering navigation not prepareForSegue:sender: which is called when preparing for the navigation
so I suggest to implement collectionView:didSelectItemAtIndexPath: as the following
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
Photo *selectedPhoto = self.photos[path.row];
// this line is the one that is responsible for navigation
[self performSegueWithIdentifier:#"Detail Segue" sender:selectedPhoto];
}
and modify prepareForSegue:sender: as the following
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Detail Segue"]) {
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
PhotoDetailVC.photo = sender;
}
}
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 =)
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];
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.