tableviewcontroller not working when called from other viewcontroller - ios

I have two tableViewControllers created in storyboard:
categories and stores.
When I select a category, it's supposed to show all stores that are in that category.
(I'm getting stores data from server, but I set a fixed category in the url so it should fetch the same two stores no matter what.)
The weird thing is that when I choose a category, storesController shows up empty,
but if I set it as initial controller, it works.
StoreTableViewController_as_initial.png
StoreTableViewController_from_categories.png
this is how I setup the cells in storeController.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
StoresCell *cell = [tableView dequeueReusableCellWithIdentifier:#"storetile"];
if(cell == nil){
cell = [[StoresCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"storetile"];
}
cell.storelabel.text = [[_results objectAtIndex:[indexPath row]]objectForKey:#"name"];
[cell.storelabel sizeToFit];
cell.subtitleOneLabel.text=[[_results objectAtIndex:[indexPath row]]objectForKey:#"neighborhood"];
cell.subtitleTwoLabel.text = [[_results objectAtIndex:[indexPath row]]objectForKey:#"city"];
NSString *distance = [NSString stringWithFormat:#"~%# km",[[_results objectAtIndex:[indexPath row]]objectForKey:#"distance"]];
cell.distanceLabel.text = distance;
NSString *imgPath = [[_results objectAtIndex:[indexPath row]]objectForKey:#"imgUrl"];
UIImage *thumb = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://andrafterdevelopment.com.br/apps/buscaabc/img/%#",imgPath]]]];
[cell.thumbImage setImage:thumb];
return cell;
}
I break at the return, the method is always called but when it's from categoriesController all labels in my cell are nil.
this is how I call storeController from categoriesController
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath{
NSDictionary *item = [_results objectAtIndex:[indexPath row]];
BOOL hasSub = [[item objectForKey:#"hasSub"] boolValue];
StoreTableViewController *storesTableViewController = [[StoreTableViewController alloc]init];
//storesTableViewController.title = [item valueForKey:#"name"];
//storesTableViewController.category = (int)[item valueForKey:#"id"];
[storesTableViewController.tableView registerClass:[StoresCell class] forCellReuseIdentifier:#"storetile"];
[self.navigationController pushViewController:storesTableViewController animated:YES];
}
I'm guessing this has to do with custom cell or maybe I'm doing it wrong by calling it this way.

If you use Storyboard, you should create your controller via Storyboard.
Set Storyboard ID in Identity inspector for your StoreTableViewController and change your method on:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath{
NSDictionary *item = [_results objectAtIndex:[indexPath row]];
BOOL hasSub = [[item objectForKey:#"hasSub"] boolValue];
StoreTableViewController *storesTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"storyboard id"];
storesTableViewController.title = [item valueForKey:#"name"];
storesTableViewController.category = (int)[item valueForKey:#"id"];
[self.navigationController pushViewController:storesTableViewController animated:YES];
}
Or you can use segues and configure your StoreTableViewController in prepareForSegue method:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"StoreTableViewControllerSegureIdentifier"]) {
StoreTableViewController *storesTableViewController = segue.destinationViewController;
storesTableViewController.title = _selectedItem.title;
storesTableViewController.category = _selectedItem.identifier;
}
}

I am guessing you have declared _results as a property in StoreTableViewController right?
If so, change your categoriesController method to:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath{
NSDictionary *item = [_results objectAtIndex:[indexPath row]];
BOOL hasSub = [[item objectForKey:#"hasSub"] boolValue];
StoreTableViewController *storesTableViewController = [[StoreTableViewController alloc]init];
storesTableViewController.title = [item valueForKey:#"name"];
storesTableViewController.category = (int)[item valueForKey:#"id"];
[self.navigationController pushViewController:storesTableViewController animated:YES];
}
And register cell in viewDidLoad.

Their are few things that i think you should check in your code.
When you are opening second view controller for selected category, did your service giving you data?
If you are getting data, then is it getting filled in array in right way?
And if everything above is fine, then had you called [tableView reloadData] method after filling data in array.

Related

To Click Button Pass Json Data To Other ViewCont``roller Tableview

I am developing an ios app..Click on button to Pass The Json Array To other UiViewController TableView To Show The Data In TableView..In TableView Array Data Pass on NSDictionary and to Use Dictionary Object. Error is [__NSCFDictionary objectAtIndex:]: Unrecognised selector sent to instance 0x7b115560']...Thanks In Advance
// Button Click
BBAuthorDetailViewController *BBAuthorDetail =[[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"BBAuthorDetail"];
[BBAuthorDetail setSelectionType:BBSelectionAuthorName];
_serverObj = [[Server alloc]init];
[_params setObject:_adDetailsObj.authorDetail forKey:#"author"];
[_serverObj BBAuthorNameWithParams:_params];
// BBAuthorDetail.data=resultsArray;
//NSIndexPath *indexPath = [BBAuthorDetail.tableview indexPathForSelectedRow];
BBAuthorDetail.data = [resultsArray objectAtIndex:indexPath.row];
NSLog(#"%#",resultsArray);
//[BBAuthorDetail setManagedObjectContext:self.managedObjectContext];
[self.navigationController pushViewController:BBAuthorDetail animated:YES];
UIViewController Table TO Show Data
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [NSString stringWithFormat:#"Cell-%li", (long)indexPath.row];
BBAdsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
// AdDetails *_adDetailsObj = (AdDetails *)[_data objectAtIndex:indexPath.row];
// NSDictionary *dic = [_data objectAtIndex:indexPath.row];
//AdDetails *_adDetailsObj = [[AdDetails alloc]init];
if (cell == nil) {
cell = [[BBAdsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.row = indexPath.row;
//[cell setDelegate:self];
}
// Error Part
NSDictionary *dic = [_data objectAtIndex:0];
cell.textLabel.text = [dic objectForKey:#"post_author"];
return cell;
}

How can I display multiple parameters of the same key from a .plist File on Objective-c?

I have this arquivo.plist below.
I looked at Apple's documentation, but I could not find how to make the listing look and I hope someone can help me.
In the first UITableView, I make a list of names present in arquivo.plist using the following code and loading the following method below.
What I'm trying to do is: When the user clicks on a tableView name, he is taken to a second screen with a new tableView that will display the "frams" of that user.
The problem is that the code I'm using to select the "frams" is the same code that I am using for listing the names on the first screen, but it is not working, because each user has only one name, but it has several "frams".
When I try to implement this, I can even assemble the array with the "frams" and pass using segue (i'll show the array with an NSLog), but this array can not be displayed as a tableView for an error that Xcode is giving me:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary length]:
unrecognized selector sent to instance 0x8b87a60'
The code from the fist view (ViewController.m) is below the contatos.plist
I hope you understand what I'm trying to do and bring me a light!
Thank you all!
a screenshot of the .plist file is bellow:
http://img268.imageshack.us/img268/7356/jl26.png
For reference and for you to better understand the issue, when the user clicks on a table name, an array is generated with "frams" this patient (patients have on average 3 frams each). The Array NSLog that it should be passed to the other page and comport a new table generates the following text:
12/12/2013 16:10:13.513 rer [24251:70 b] (
{
1 = 11;
2 = 12;
3 = 13;
}
I think that's where the problem lies, because this method of Array can not be implemented in a TableView, so I look a light of a better way to mount this array and select frams when I click a patient
So here is my ViewController.m:
#import "ViewController.h"
#import "Contato.h"
#import "perfilViewController.h"
#interface ViewController ()
-(void) loadContacts;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadContacts];
}
-(void) loadContacts
{
NSString *plistCaminho = [[NSBundle mainBundle] pathForResource:#"contatos"
ofType:#"plist"];
NSDictionary *pl = [NSDictionary dictionaryWithContentsOfFile:plistCaminho];
NSArray *dados = [pl valueForKey:#"contatos"];
contatos = [[NSMutableArray alloc] init];
for (NSDictionary *item in dados) {
NSString *nome = [item valueForKey:#"nome"];
NSString *telefone = [item valueForKey:#"telefone"];
NSString *fram = [item valueForKey:#"fram"];
Contato *c = [[Contato alloc] initWithNome:nome andTelefone:telefone andFram:fram];
[contatos addObject:c];
}
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return contatos.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CelulaContatoCacheID = #"CelulaContatoCacheID";
UITableViewCell *cell = [self.tabelaContatos dequeueReusableCellWithIdentifier:CelulaContatoCacheID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CelulaContatoCacheID];
}
Contato *contato = [contatos objectAtIndex:indexPath.row];
cell.textLabel.text = contato.nome;
return cell;
}
#pragma mark -
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Contato *contato = [contatos objectAtIndex:indexPath.row];
NSString *msg = [NSString stringWithFormat:#"Fram:%#",contato.fram];
fran = [[NSMutableArray alloc] init];
fran = [NSMutableArray arrayWithObject:contato.telefone];
NSLog(#"finalmente eu consegui essa porra!!!%#", fran);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Contato"
message:msg
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[self.tabelaContatos deselectRowAtIndexPath:indexPath animated:YES];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"vai"]) {
NSIndexPath *indexPath = [self.tabelaContatos indexPathForSelectedRow];
perfilViewController *destViewController = segue.destinationViewController;
Contato *contato = [contatos objectAtIndex:indexPath.row];
fran = [[NSMutableArray alloc] init];
fran = [NSMutableArray arrayWithObject:contato.fram];
destViewController.frans = fran;
NSLog(#"%#%#", fran, destViewController.frans);
}
}
#end
I'd firstly do:
//declare NSDictionary *pl; in the ViewController.h
pl = [NSDictionary dictionaryWithContentsOfFile:plistCaminho];
Then to display Names, i'd simply use the dictionary as such:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[pl objectForKey:#"contatos"] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...
//following commented line not needed anymore
//Contato *contato = [contatos objectAtIndex:indexPath.row];
cell.textLabel.text = [[[pl objectForKey:#"contatos"]
objectAtIndex:indexPath.row]
objectForKey:#"nome"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//following commented line not needed anymore
//Contato *contato = [contatos objectAtIndex:indexPath.row];
//NOTE: fran is a dictionary now
//change "fran" declaration in the ViewController.h to
//NSDictionary *fran;
fran = [[NSDictionary alloc] init];
fran = [[pl objectForKey:#"contatos"]
objectAtIndex:indexPath.row];
NSLog(#"finalmente eu consegui essa porra!!!%#", fran);
//...
//don't deselectRow (the indexPathForSelectedRow will not work correctly later)
//[self.tabelaContatos deselectRowAtIndexPath:indexPath animated:YES];
}
then on -prepareForSegue i'd pass the dictionary associated with the selected row:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"vai"]) {
NSIndexPath *indexPath = [self.tabelaContatos indexPathForSelectedRow];
perfilViewController *destViewController = segue.destinationViewController;
//following commented line not needed anymore
//Contato *contato = [contatos objectAtIndex:indexPath.row];
//NOTE: fran is a dictionary now
//change "fran" declaration in the ViewController.h to
//NSDictionary *fran;
fran = [[NSDictionary alloc] init];
fran = [[[pl objectForKey:#"contatos"]
objectAtIndex:indexPath.row]
objectForKey:#"fram"];
//NOTE: destViewController.frans should be a dictionary
//handle it appropriately
destViewController.frans = fran;
}
}
so basically, all dictionary use, no need for Contato *contato at all.
EDIT: As for your current method, you would be better off replicating the same structure.
As in:
[array of names] has {dictionary with user details} having a key that has {dictionary of frams}
I'd recommend you not using a dictionary to store your Fram values, use an array instead.
This way, you can get the Fram values like this:
for (NSDictionary *item in dados) {
NSString *nome = [item valueForKey:#"nome"];
NSString *telefone = [item valueForKey:#"telefone"];
NSArray *fram = [item valueForKey:#"fram"];
Contato *c = [[Contato alloc] initWithNome:nome andTelefone:telefone andFram:[fram objectAtIndex:index]];
[contatos addObject:c];
}
Where index is an integer variable you'll have to work out how to handle.
PS: be a little more polite when logging you app ;)

To Segue or to didSelectRowAtIndexPath?

Below is the code that I am currently running. I have a storyboard setup with a nav controller and tableview controller and a view controller. I am trying to pass the name from the NSDictionary that I have setup for the Table to the detail view controller. Should I use prepareforsegue or didselectrowatindexpath and how would I get the name out of the dictionary to pass it along?
#import "FMInboxViewController.h"
#import "FMDetailViewController.h"
#interface FMInboxViewController ()
#end
#implementation FMInboxViewController
#synthesize keyArray;
#synthesize tableArray;
#synthesize tblDictionary;
#synthesize filteredArray;
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *ary=[[NSMutableArray alloc]init];
[ary addObject:#"Adam"];
[ary addObject:#"Fred"];
[ary addObject:#"Angel"];
// ... many similar entries
[ary addObject:#"James"];
[ary addObject:#"Mukthesh"];
self.tblDictionary =[self fillingDictionary:ary];
}
Table View Data Source
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [keyArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSArray *ary = [self.tblDictionary valueForKey:[keyArray objectAtIndex:section]];
return [ary count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *key = [keyArray objectAtIndex:[indexPath section]];
NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
NSString *cellTitle = [array objectAtIndex:[indexPath row]];
cell.textLabel.text = cellTitle;
// Configure the cell...
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *title = [keyArray objectAtIndex:section];
return title;
}
//-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// NSString *key = [keyArray objectAtIndex:[indexPath section]];
// NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
// self.selectedName = [array objectAtIndex:indexPath.row];
// NSLog(#"Selected Name in Did select: %#", self.selectedName);
//
// [self performSegueWithIdentifier:#"showDetail" sender:self];
//}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *section = [self.tableView indexPathForSelectedRow];
NSString *key = [keyArray objectAtIndex:section];
NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
NSString *cellTitle = [array objectAtIndex:[indexPath row]];
NSLog(#"Selected Name in Did select: %#", self.selectedName);
}
}
Helper methods
#pragma mark - Helper Methods
- (NSMutableDictionary *)fillingDictionary:(NSMutableArray *)sentArray {
keyArray = [[NSMutableArray alloc] init];
[keyArray removeAllObjects];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[sentArray sortUsingSelector:#selector(compare:)];
for ( NSString *str in sentArray) {
NSString *charVal = [str substringToIndex:1];
NSString *charStr = [NSString stringWithString:charVal];
NSLog(#" charStr = %#", charStr);
if (![keyArray containsObject:charStr]) {
NSMutableArray *charArray = [[NSMutableArray alloc] init];
[charArray addObject:str];
[keyArray addObject:charStr];
[dic setValue:charArray forKey:charStr];
}
else {
NSMutableArray *prevArray = (NSMutableArray *)[dic valueForKey:charStr];
[prevArray addObject:str];
[dic setValue:prevArray forKeyPath:charStr];
}
}
return dic;
}
#end
OK, I changed that section to look like this
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *key = [keyArray objectAtIndex:[indexPath section]];
NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
self.selectedName = [array objectAtIndex:indexPath.row];
NSLog(#"Selected Name in Did select: %#", self.selectedName);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
FMDetailViewController *dvc = (FMDetailViewController *)segue.destinationViewController;
dvc.name = self.selectedName;
}
However now when I select row the name won't show up in the detail controller on the first press. If you go back and select another name the first name that you pressed then shows up in the view controller. Any suggestions on why this occurs?
You need to use both, in didSelectRowAtIndexPath you should call [self performSegueWithIdentifier:#"identifier" sender:self];
In the same View Controller you should have the prepareForSegue method grab the destinationViewController out of the segue, and then set whatever properties on that view controller that you wish to set.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.someProperty = [self.someArray objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"segueID" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *vcToPushTo = segue.destinationViewController;
vcToPushTo.propertyToSet = self.someProperty;
}
If possible (and this is the case in almost all standard scenarios), I would use Interface Builder to trigger the segue. You still need to implement prepareForSegue: to configure the destination view controller.
In order to create a segue in IB which triggers a detail view when tapping on a cell or an accessory button (on the right most side of the cell) perform these steps:
Control drag from Table View Cell to the destination view controller and release the mouse or trackpad. This opens small selection panel.
Choose the source of the trigger, either "Selection segue" or "Accessory action" and the type of the segue ("push", "modal" or "custom").
In the Attributes Inspector pane define the "Identifier" of the segue, e.g. "UserShowSegue".
Here's an image from a Demo storyboard in IB which illustrates how the "Table View Cell" in the "Users" view controller is setup to trigger a "push" segue to a detail view controller:
Might be an old question, but to be more detailed for whom it may concern:
1- Use both as '(#Peter-Foti)' mentioned.
2- Segue should be linked from the ParentVC to the DestinationVC (NOT from the Prototype Cell).
3- Sender should be set properly.
4- set your '#property (someProperty)'.
SAMPLE CODE:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.someProperty = [self.someArray objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"segueID" sender:self.someProperty];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *vcToPushTo = segue.destinationViewController;
vcToPushTo.propertyToSet = sender;
}
Because didSelectRowAtIndexPath can be replaced with storyboard visual programming, I recommend to do all the logic in the prepareForSegue like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let cell = sender as! UITableViewCell
let indexPath = tableView.indexPath(for: cell)!
... and then use indexPath to set up the destination
}

how to show the sqlite data in uitableview on otherviewcontroller?

i have viewcontroller .h .m and .xib that contain registration form to insert update and delete.
and i have other xib that contain uitableview that show the sqlite data .how can i display ???
i write the code but its gives the error on array of viewcontroller page and other control that are used in viewcontroller.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [[data objectAtIndex:indexPath.row] valueForKey:#"name"];
cell.detailTextLabel.text = [[data objectAtIndex:indexPath.row] valueForKey:#"salary"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
name.text = [[data objectAtIndex:indexPath.row] valueForKey:#"name"];
salary.text = [[data objectAtIndex:indexPath.row] valueForKey:#"salary"];
}
here data is NSArray in viewcontroller.h file gives error here
and also in didSelectRowAtIndexPath method name.text and salary.text gives error because it is the textfield of viewcontroller.
how can i solved it ?????
You have to make sure the data array should be available in otherViewController. For that create a array property in .h file of OtherViewController and while loading this view controller, assign the data array to this property.
Well as you are using SQlite database, you can fetch the data from the database(you'll need to add additional code) in OtherViewController and display it the tableView there.
Also you can't access the private variables of a view controller inside a different view controller. You will have to create properties for them or create public methods.
do it like this.. First create temporary dictionary and than fetch the data from that..
NSDictionary * tmpDictn = [data objectAtIndex:indexPath.row];
cell.textLabel.text = [tmpDictn valueForKey:#"name"];
cell.detailTextLabel.text = [tmpDictn valueForKey:#"salary"];
And same here..
NSDictionary * tmpDictn = [data objectAtIndex:indexPath.row];
name.text = [tmpDictn valueForKey:#"name"];
salary.text = [tmpDictn valueForKey:#"salary"];

Loading data from cell to detailView always show the last data

I have UITableView with some data from backend, I have everything in table,3 UILable and I will get that information from backend and I can show them in table row, when I click on row I want to have the same label in my detail view, but now, I have just one information in all my detail view, same information, just load the last row for all detailView,
would you please help me in this implementation,
Thanks in advance!
cellForRowAtIndexPath method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
static NSString *CellIdentifier = #"BooksCell";
BooksCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell =[ [[NSBundle mainBundle] loadNibNamed:#"BooksCell" owner:nil options:nil]
lastObject];
}
_books = [server get_tests:10 offset:0 sort_by:0 search_for:#""];
_t = [NSMutableString stringWithFormat:#"%# ", [_books objectAtIndex:indexPath.row]];
NSString *testdata = _t;
_components = [testdata componentsSeparatedByString:#","];
NSLog(#"_components: %#",_components);
for (NSString *aComponent in _components) {
if ([aComponent hasPrefix:#"title"]) {
_subComponents = [aComponent componentsSeparatedByString:#":"];
_titleString = [_subComponents[1] stringByTrimmingCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:#"\""]];
}if ([aComponent hasPrefix:#"authors"]){
_subComponents = [aComponent componentsSeparatedByString:#":"];
_writerString = [_subComponents[1] stringByTrimmingCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:#"\""]];
}if ([aComponent hasPrefix:#"name"]){
_subComponents = [aComponent componentsSeparatedByString:#":"];
_publisherString = [_subComponents[1] stringByTrimmingCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString:#"\""]];
break;
}
}
cell.bookTitle.text = _titleString;
cell.writer.text = _writerString;
cell.publisher.text = _publisherString;
return cell;
}
didSelectRowAtIndexPath method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
BooksDetailView *c = [[BooksDetailView alloc] init];
[self.booksTable addSubview:c.view];
c.bDetailTitle.text = _titleString;
c.bDetailWriter.text = _writerString;
c.bDetailPublisher.text = _publisherString;
}
_titleString, _writerString and _publisherString seem to be instance variables
of the table view controller, and these are overwritten in cellForRowAtIndexPath
each time a cell is displayed.
You have to use the indexPath in didSelectRowAtIndexPath to get the correct element
of your data source.
Note also that fetching all elements from the server in cellForRowAtIndexPath
is very ineffective, because this method is called frequently.
You should fetch the data once (e.g. in viewDidLoad) and assign
the fetched array to an instance variable or property of the view controller.
Then you can access the elements from the array in cellForRowAtIndexPath and in
didSelectRowAtIndexPath.
Add a property
#property (strong, nonatomic) NSArray *books;
to the view controller. Fetch the data in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
self.books = [server get_tests:10 offset:0 sort_by:0 search_for:#""];
// ... other stuff ...
}
In cellForRowAtIndexPath you just get the element from the array.
Also, instead of all that string manipulation, you should use the model class
and property accessors generated by the Thrift API.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
static NSString *CellIdentifier = #"BooksCell";
BooksCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell =[[[NSBundle mainBundle] loadNibNamed:#"BooksCell" owner:nil options:nil] lastObject];
}
YourModelClass *book = self.books[indexPath.row];
cell.bookTitle.text = book.title;
// ...
return cell;
}
And similarly in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
BooksDetailView *c = [[BooksDetailView alloc] init];
[self.booksTable addSubview:c.view]; // WHY THAT?
YourModelClass *book = self.books[indexPath.row];
c.bDetailTitle.text = book.title;
// ...
}

Resources