how to populate uitableviewcell data to other class? - ios

my code snippet //
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// [tableView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.section == 0)
{
if(indexPath.row == 1)
{
WebServiceHandler *handler = [[WebServiceHandler alloc]init];
handler.requestType = eSuburb;
NSMutableURLRequest *searchDetailsRequest = [Service parseGetSuburb:nil];
NSLog(#"user details request of str== %#",searchDetailsRequest);
[handler placeWebserviceRequestWithString:searchDetailsRequest Target:self Selector:#selector(getListOfSuburb:)];
}
after response it jumps into another class with list of all it is data,among all those data I want to populate with it one which user selects

Not sure how you are doing this, but here is how if you are using segues. In this example, each of my table cells contained their relative information in an NSMutableDictionary. The receiving view controller had a NSMutableDictionary property to receive all of the sent data. The last two lines create a ViewController object and has its Dictionary property equal the Dictionary being sent from the selected cell in the table view.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSString *identifier = segue.identifier;
if ([identifier isEqualToString:#"SegueName"]) {
// first get data
NSIndexPath *selectedIndexPath = self.tableView.indexPathForSelectedRow;
NSMutableDictionary *cellData = self.aDictionary[selectedIndexPath.row];
ViewController *nextViewController = segue.destinationViewController;
nextViewController.aDictionary = cellData;
}
}

I would Suggest against using the callback method here. That is not the right way to carry this out.
According to my understanding, what you want to do is once the user selects a row, you wish to pass the selected row's data back to the viewcontroller(lets assume 'vcA') which called the one with the tableview('vcB')...
If this is so you should create a protocol and hence use a delegate to notify the viewcontroller 'vcA' about the selection event and hence pass the required data just as #inertiatic suggested.

Related

How do I send the chosen cell array to another view in Objective-C?

I am trying to send an NSMutableArray of the chosen cell to another view when a cell is clicked. I have the array of the chosen cell, but I can't get it to pass over.
"SearchResultsModalTableViewController.m"
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *aVenue = [self.venues objectAtIndex:indexPath.row];
DetailSearchResultViewController *detailVC =[[DetailSearchResultViewController alloc]init];
detailVC.venueInfo = aVenue;
NSLog(#"%#",aVenue);
}
When you use storyboards, you usually add segues from table cells to a destination storyboard. If that is what you are doing, then the way to deal with the selection is in the prepareForSegue: method of your view controller.
Here is an example. I am assuming that DetailSearchResultViewController in your code is a UINavigationController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailSearchResultViewController* destinationViewController = (DetailSearchResultViewController*)segue.destinationViewController;
NSIndexPath *p = self.tableView.indexPathForSelectedRow;
NSUInteger idx = p.row;
NSMutableArray *aVenue = [self.venues objectAtIndex:indexPath.row];DetailSearchResultViewController *detailVC =[[DetailSearchResultViewController alloc]init];
destinationViewController.venueInfo = aVenue;
[super prepareForSegue:segue sender:sender];
}

How to pass data values to other ViewController Objective-C using NSDictionary?

I'm following a tutorial from a book and everything went fine untill i had to recieve the data from the tableView, i must mention that i modified some of the basic tutorial to fit my needs as i work with JSON values comming from a API. It crashes when i reference the value using self and says that the variables is nil. must also mention that the label has been added as a reference outlet and the customClass also as been created and added referenced with the View. Aditional to this added properly Segue to the detailViewController
UserDetailViewController.h
#interface UserDetailViewController : UIViewController
#property (nonatomic, strong) NSString *labelName;
#property (nonatomic, strong) IBOutlet UILabel *detailLabelName;
#end
UserDetailViewController.m
This is the code that does the transition between Table and detailView but there are a few values that does not belong to the code i have such as recipeName and recipeNames as you can see below:
recipeName is on my code labelName
recipeNames is on my code a dictionary [dictionary objectForKey:#"name"]
and have no idea how to put this part together. :(
// Here is where I handles the Data Transfer
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"userDetailView"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
destViewController.recipeName = [recipeNames objectAtIndex:indexPath.row];
}
}
According to my understanding, you want to set text for detailLbelName depending on labelName. And this value is coming from your parent view controller.
You must be doing something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UserDetailViewController *detailController = [[UserDetailViewController alloc]initWithNibName:#"UserDetailViewController" bundle:nil];
self.detailController.lableName = #"Your Text According to Cell"
[self.navigationController pushViewController:detailController animated:YES];
}
In your UserDetailViewController:
- (void)viewWillAppear
{
self.title = self.labelName;
[self.detailLabelName setText:self.labelName];
}
To receive the data from tableView need to handle tableView delegate did select method and passed all required data to detailLabelName then refresh the screen.
Move the assignment lines in viewDidLoad to viewWillAppear.
- (void)viewWillAppear
{
self.title = self.labelName;
_detailLabelName.text = _labelName; // this is the breakpoint
}
Then, hwever you are storing the string in the table view (i assume you mean the cells specifically) then you may assign the value extracted from the table view cell after creating the detail view controller but before it is pushed onto the navigation stack and crashes your app.
please try this
In
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
of your table view do this.
UserDetailViewController *detailsView = [[UserDetailViewController alloc] initWithNibName:"Your nib name" bundle:[NSBundle mainBundle]];
UITableViewCell *reqDcell = [tableView cellForRowAtIndexPath:indexPath];
detailsView.labelName = //Text from reqDcell goes here. In particular the recipe name
[self.navigationController pushViewController:tableViewControls animated:YES];
Hope this helps.
********** EDIT ************
Ok so inorder to pass values using a dictionary , you would need an array of dictionaries which hold your data.
In terms of the link you posted, i have modified it for your understanding to use dictionaries.
recipeNames = #[[NSDictionary dictionaryWithObject:#"Mushroom" forKey:#"Recipie Name"],
[NSDictionary dictionaryWithObject:#"Hamburger" forKey:#"Recipie Name"],
[NSDictionary dictionaryWithObject:#"Pasta" forKey:#"Recipie Name"],
[NSDictionary dictionaryWithObject:#"Pizza" forKey:#"Recipie Name"],
[NSDictionary dictionaryWithObject:#"Noodles" forKey:#"Recipie Name"]];
The dictionary here will hold the json data that you have.
in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// Display recipe in the table cell
NSDictionary *dict = [recipeNames objectAtIndex:indexPath.row];
cell.nameLabel.text = [dict valueForKey:#"Recipie Name"];
and the prepareForSegue function.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
NSDictionary *dict = [recipeNames objectAtIndex:indexPath.row];
destViewController.recipeName = [dict valueForKey:#"Recipie Name"];
}
}
I hope this is helpful

How to pass the in-place edited content back to the previous tableview controller (update the model)

I have two table views, one called mainTableViewController (mtvc), the other called detailTableViewController (dtvc). It's very typical click the accessory button on the main tableview cell bring you to the detail tableview kinda thing.
In the prepareForSegue method, the data passed from the main tableview to detail tableview is a NSMutableArray called item.
And this is how I got it displayed: cell.detailTextLabel.text = self.item[indexPath.row];
The cool thing is I managed to do in-place editing on the detail table view cell (overwrote the NSTableViewCell, added a UITextField as subview to each cell).
everything works, the last thing I spent whole day cannot figure out is how do I update the NSMutableArray item after in-place editing taken place, the ultimate goal is in-place editing, and the main tableview data shall reflect the change.
I tried to use delegation and protocol but it does not work (the in-place edited content didn't got passed back, part of the reason is I don't know how to capture the edited content, it's not like it's a text field with a name, I can't just do updatedContent = self.myTextField.text to grab the change)
I'm running out of ideas, any help would be highly appreciated, thanks.
Here's the prepareForSegue in the main tableview controller
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toInventoryDetail"]) {
NSMutableArray *selectedItem = nil;
if (self.searchDisplayController.active) {
selectedItem = _searchResults[[sender row]];
} else {
selectedItem = _appDelegate.items[[sender row]];
}
UPFInventoryDetailTableViewController *idtvc = segue.destinationViewController;
idtvc.item = selectedItem;
}
}
and here's the cellForRowAtIndex at the detail tableview controller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UPFEditableUITableViewCell *cell = [[UPFEditableUITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier];
cell.textLabel.text = _appDelegate.title[indexPath.row];
cell.detailTextLabel.text = self.item[indexPath.row];
[cell showEditingField:YES];
return cell;
}
I wrote the delegation but delete them after cause they didn't work.
I had an idea, still using delegation and protocol obviously: when the 'done' button in the detail tableview hit, I go grab all the row contents and build a new array, using delegation to pass this new array back to the main tableview controller, add this new array into the model meanwhile delete the old one. The tricky thing is still HOW CAN I GRAB ALL THE CONTENTS in the detail tableview?
update:
Haha! I think solved half of the puzzle !
here's the solution for the detail tableview controller
- (IBAction)doneUpdate:(UIBarButtonItem *)sender {
[self.delegate addItem:[self newItem]];
}
- (NSMutableArray *)saveItem
{
NSMutableArray *newItem = [[NSMutableArray alloc] init];
NSArray *indexPathes = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in indexPathes) {
UPFEditableUITableViewCell *cell = (UPFEditableUITableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
[newItem addObject:cell.editField.text];
}
return newItem;
}
and here's the main tableview controller
- (void)addItem:(NSArray *)item
{
//take the updated item then insert the items array as new item
[_appDelegate.items addObject:item];
//remove the selected item (the one being updated) from the items array
[_appDelegate.items removeObject:_appDelegate.selectedItem];
[self.tableView reloadData];
[self.navigationController popViewControllerAnimated:YES];
}
When you creating a cell - give tags to your UITextFields
You can collect data entered by its delegate methods - you can either make NSDictionary/ key value pairs or you can add it to NSArray.
- (void)textFieldDidEndEditing:(UITextField *)textField {
if(textField.tag == 11) {
// you can add it to your desired array/dictionary
}
}
OR
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if(textField.tag == 11) {
// you can add it to your desired array/dictionary
}
}
You can use Delegation/Protocol or store this values in NSUserDefault and get it back on mainViewController.
Do you have a separate data model class(classes) for your selectedItem? That would be the appropriate way to persist data between the two TableViewControllers. It can be Core Data or simply a NSMutableArray that lives in memory. The DetailViewController updates the item and saves the changes, then the mainTableViewController reloads the TableView (or even just the data backing the previously edited cell.
Perhaps even consider the Model-View-Controller-Store pattern promoted by BigNerdRanch.

How to pass and collect info what was pressed in UITableView

I need more help with my first Table View app.
I have .plist with continents, countries and other info:
I work with a StoryBoard and I have 3 View Controllers (MasterVC - for continents, MiddleVC - for countries, DetailVC - for detailed info). I have already continents displayed in UITableView on my MysterVC. Now I want to pass information about what was pushed to the MiddleVC, for example that Europe was pushed and the to display European countries in a table view on my MiddleVC.
I guess that I should do it in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
//is it correct way to catch the info about which continent was pressed?
NSString *ContinentName = [[world allKeys] objectAtIndex:indexPath.row];
//I don't know how to pass the info forward
}
Or maybe I should use segue for passing data?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showMiddle"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDate *object = _objects[indexPath.row];
//??is everything what needed here??
[[segue destinationViewController] setDetailItem:object];
}
}
And I am not sure how to deal with the passed info from MasterVC, here in MiddleVC. Although I prepared some initial coding:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
//I think countries arrays will be needed here
NSArray *namesOfAfricanCountries = [africa allKeys];
NSString *AfricanCountryName = [namesOfAfricanCountries objectAtIndex:indexPath.row];
NSArray *namesOfEuropeanCountries = [europe allKeys];
NSString *EuropeanCountryName = [namesOfEuropeanCountries objectAtIndex:indexPath.row];
//how to feel cells only with the proper continent's countries?
cell.textLabel.text = ???;
return cell;
}
Will appreciate any help.
Are you using a UINavigationController? If so:
Setup a 'push' segue from your Master VC to your Detail VC and have a property in your details VC to hold the 'continent' dictionary.
implement 'prepareForSegue', here you can use the indexPathForCell: on the sender argument to find out which cell was tapped.
Use the row in the index path to locate the country in your dictionary
In your prepare for segue, use segue.destinationViewController to get a handle on your detail VC and set it's continent property to the country dictionary from your data source. (you only want to pass forward the continent dictionary containing the countries in that continent, not your whole data source).
Then in the detail VC' cellForRowAtIndexPath:
then if you only want to display the country name in the cell assuming the names are keys...
NSString *key = [self.continentDict allKeys][indexPath.row];
cell.textLabel.text = key;

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