uitableview reloadRowsAtIndexPaths not working - iphone

I have a tableviewcell in the RegisterViewController, when i click on it, it push to the SelectCityViewController where i can pick a city from a uipickerview. and I have defined a delegate in the SelectCityViewController. But when i implement the delegate method, i got the city back from the pickerview and the selected indexpath from didSelectRowAtIndexPath in RegisterViewController. When i check the log, i get the city, and the selected indexpath. but when i call reloadRowsAtIndexPaths, the cell still got the old titlelabel text. the code:
SelectCityViewController.h
#protocol SelectCityDelegate <NSObject>
- (void)didGetCity:(City *)city;
#end
SelectCityViewController.m
- (void)finished:(UIBarButtonItem *)buttonItem
{
if ([self.delegate respondsToSelector:#selector(didGetCity:)]) {
[self.delegate didGetCity:self.city];
}
NSLog(#"%#", self.city.city);
[self.navigationController popViewControllerAnimated:YES];
}
RegisterViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 2) {
self.selectedIndexPath = indexPath;
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
SelectCityViewController *signUp = [storyBoard instantiateViewControllerWithIdentifier:#"SignVC"];
signUp.delegate = self;
[self.navigationController pushViewController:signUp animated:YES];
}
}
- (void)didGetCity:(City *)city
{
NSLog(#"%#", city.city);
NSLog(#"%#", selectedIndexPath);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:selectedIndexPath];
cell.textLabel.text = city.city;
[self.tableView reloadRowsAtIndexPaths:#[selectedIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}

I think the problem is in the below code you don't have to set the value here, because when you will reload, it will override the value with what is in the function where you are creating your cells.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:selectedIndexPath];
cell.textLabel.text = city.city;
Just reload the cell, and put above code in your
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Cell intialization and other things
cell.textLabel.text = city.city;
}

didGetCity needs to update the model that backs the table, not the table cell itself. How do you answer numberOfRowsInSection:? With the count of some array?
That array at index selectedIndexPath.row needs to change. cellForRowAtIndexPath: should initialize the cell with that same data. Then your didGetCity method updates the array and reloads. It should not refer to cells.

Related

expanding cell to show a nib file view

I want to expand the cell when selected to show a row of buttons like the image above. I have a xib file which shows a cell that is 320 wide x 140 tall. I have subclassed that UITableViewCell. Additionally I have another xib file that has the row of buttons as shown in blue ink in the image above.
I am able to load the row of buttons using initWithCoder using this answer from a really smart guy!
However, it overwrites all my other views inside the MyCustomCell.
How can I load the xib just when the cell expands so that it is positioned in the lower half of the 140pt tall cell?
After doing a little more research, I found a different way to do something like what you want using just one cell. In this method, you have just the taller cell, but return a height that only lets you see the top half of the cell unless its selected. You have to do two things in the design of your cell to make this work. First select the box for "clip subviews" in IB, so the buttons won't show outside their view (the cell). Second, make the constraints such that the buttons are all lined up vertically with each other and give one of them a vertical spacing constraint to one of the UI elements in the top of the cell. Make sure none of the buttons has a constraint to the bottom of the cell. By doing this, the buttons will maintain a fixed distance with the top elements (which should have a fixed space to the top of the cell), which will cause them to be hidden when the cell is short. To animate the change in height, all you have to do is call beginUpdates followed by endUpdates on the table view.
#import "TableController.h"
#import "TallCell.h"
#interface TableController ()
#property (strong,nonatomic) NSArray *theData;
#property (strong,nonatomic) NSIndexPath *selectedPath;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"TallCell" bundle:nil] forCellReuseIdentifier:#"TallCell"];
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine"];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqual:self.selectedPath]) {
return 88;
}else{
return 44;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TallCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TallCell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.selectedPath isEqual:indexPath]) {
self.selectedPath = nil;
}else{
self.selectedPath = indexPath;
}
[tableView beginUpdates];
[tableView endUpdates];
}
This, I think gives you the desired animation when you pick the first cell, but you get a somewhat different animation if you then pick a cell below the currently selected one. I don't know of any way around that.
I'm not sure what you have in your two xib files, but the way I would do it is to have one xib file for the shorter cell, and one for the taller cell (that has everything in it that you show in your drawing). I did it like this, with two xib files like I mention above:
#import "TableController.h"
#import "ShortCell.h"
#import "TallCell.h"
#interface TableController ()
#property (strong,nonatomic) NSArray *theData;
#property (strong,nonatomic) NSIndexPath *selectedPath;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"ShortCell" bundle:nil] forCellReuseIdentifier:#"ShortCell"];
[self.tableView registerNib:[UINib nibWithNibName:#"TallCell" bundle:nil] forCellReuseIdentifier:#"TallCell"];
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine"];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqual:self.selectedPath]) {
return 88;
}else{
return 44;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (! [self.selectedPath isEqual:indexPath]) {
NSLog(#"returning short");
ShortCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ShortCell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row];
return cell;
}else{
NSLog(#"returning long");
TallCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TallCell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row];
return cell;
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if ([self.selectedPath isEqual:indexPath]) {
self.selectedPath = nil;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
return;
}
NSIndexPath *lastSelectedPath = self.selectedPath;
self.selectedPath = indexPath;
if (lastSelectedPath != nil) {
[self.tableView reloadRowsAtIndexPaths:#[indexPath,lastSelectedPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}else{
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}

ios push array to uitableview

The best answer on stackoverflow for pushing an array to a tableView cell is "start with something easier". I think we can do better than that...
I believe I have everything in place except I can not find the proper way to address getting the data from the rootView. See Below.
The below code pushes an array to DetailView Controller with three cells in a group with "Get Cell Info Here" in top cell. Can someone explain what I need to do to get the actual data into the top cell? Thanks
RootViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
DetailViewController *selectedCell = [[DetailViewController alloc] initWithStyle:UITableViewStyleGrouped];
[self.navigationController pushViewController:selectedCell animated:YES];
}
DetailViewController.h
#interface DetailViewController : UITableViewController {
NSArray *displayCell;
}
#end
DetailViewController.m
- (void)viewWillAppear:(BOOL)animated
{
//Display the selected cell data
displayCell = [[NSArray alloc] initWithObjects:#"Get Cell Info Here", nil];
//Set the title of the navigation bar
self.navigationItem.title = #"wtf";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] ;
// Make cell unselectable
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *cellText = nil;
switch ( indexPath.row ) {
case 0: {
cellText = [displayCell objectAtIndex:indexPath.row];
break ;
}
case 1: {
break ;
}
case 2: {
break ;
default:
break;
}
}
cell.textLabel.text = cellText;
return cell;
}
Add a property to DetailViewController as follows:
#property (nonatomic, retain) NSArray *passedItems;
Then have root view controller pass the items as follows:
selectedCell.passedItems = passedItems; // passedItems is array in rootview controller
Then you can use passedItems in DetailedViewController.

How to pass data back from detail view controller to uitableview?

In my app i making use of uitable to select category from my list.
my task is,when ever user click or select a cell he should be able to view the selected cell detail in next view(detail view). and when he select the item in a detail view he should be able to move back in a table view and should be able to see the selected item in a rootivew controller.
i am able to navigate properly from tableview to detail view,but i am not able to show the item which is selected in detail view to rootviewcontroller.
please help me out with this issue.
image one is my rootview controller page.
for example : if user select #"make" he will able to see all the releated category of #"make"
. in a next page(which image2).
image to is my detail page.
and when user select #"abarth" it should be display in a rootview controller page(which is page one).
following is my code of rootview controller page:
- (void)viewDidLoad
{
self.car = [[NSArray alloc]initWithObjects:#"Make",#"Model",#"Price Min",#"Price Max",#"State",nil];
[super viewDidLoad];
}
-(NSInteger) numberOfSectionInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.car count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *TextCellIdentifier = #"Cell";
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:TextCellIdentifier];
if (cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TextCellIdentifier];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = [self.car objectAtIndex:[indexPath row]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (0 == indexPath.row)
{
NSLog(#"0");
self.detailcontroller.title = #"Make";
}
else if (1 == indexPath.row)
{
NSLog(#"1");
self.detailcontroller.title = #"Model";
}
else if (2 == indexPath.row)
{
NSLog(#"2");
self.detailcontroller.title = #"Price Min";
}
else if (3 == indexPath.row)
{
self.detailcontroller.title = #"Price Max";
}
else if (4 == indexPath.row)
{
NSLog(#"3");
self.detailcontroller.title = #"State";
}
[self.navigationController
pushViewController:self.detailcontroller
animated:YES];
}
following is my detail view page code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if ([self.title isEqualToString:#"Make"])
{
detail = [[NSArray alloc]initWithObjects:#"Any Make",#"Abarth",#"AC",#"ADAYER",#"Adelaide",#"ALFA ROMEO",#"ALLARD",#"ALPINE-RENAULT",#"ALVIS",#"ARMSTRONG",
#"ASTON MARTIN",#"AUDI",#"AUSTIN",#"AUSTIN HEALEY",#"Barossa",#"BEDFORD",
#"BENTLEY",#"BERTONE",#"BMW",#"BOLWELL",#"BRISTOL",#"BUICK",#"BULLET",
#"CADILLAC",#"CATERHAM",#"CHERY",#"CHEVROLET",#"CHRYSLER",#"CITROEN",
#"Country Central",#"CSV",#"CUSTOM",#"DAEWOO",#"DAIHATSU",#"DAIMLER",
#"DATSUN",#"DE TOMASO",#"DELOREAN",#"DODGE",#"ELFIN",#"ESSEX",
#"EUNOS",#"EXCALIBUR",#"FERRARI",nil];
if ([self.title isEqualToString:#"Abarth"])
{
detail = [[NSArray alloc]initWithObjects:#"HI", nil];
}
}
else if ([self.title isEqualToString:#"Model"])
{
detail = [[NSArray alloc]initWithObjects:#"Any Model", nil];
}
else if ([self.title isEqualToString:#"Price Min"])
{
detail = [[NSArray alloc]initWithObjects:#"Min",#"$2,500",
#"$5,000",
#"$7,500",
#"$10,000",
#"$15,000",
#"$20,000",
#"$25,000",
#"$30,000",
#"$35,000",
#"$40,000",
#"$45,000",
#"$50,000",
#"$60,000",
#"$70,000",
#"$80,000",
#"$90,000",
#"$100,000",
#"$500,000",
#"$1,000,000",nil];
}
else if ([self.title isEqualToString:#"Price Max"])
{
detail = [[NSArray alloc]initWithObjects:#"Max",
#"$2,500",
#"$5,000",
#"$7,500",
#"$10,000",
#"$15,000",
#"$20,000",
#"$25,000",
#"$30,000",
#"$35,000",
#"$40,000",
#"$45,000",
#"$50,000",
#"$60,000",
#"$70,000",
#"$80,000",
#"$90,000",
#"$100,000",
#"$500,000",
#"$1,000,000",nil];
}
else if ([self.title isEqualToString:#"State"])
{
detail = [[NSArray alloc]initWithObjects:#"Any State",
#"Australian Capital Territory",
#"New South Wales",
#"Northern Territory",
#"Queensland",
#"South Australia",
#"Tasmania",
#"Victoria",
#"Western Australia",nil];
}
[self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [detail 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];
}
cell.textLabel.text = [detail objectAtIndex:
[indexPath row]];
cell.font = [UIFont systemFontOfSize:14.0];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.navigationController popViewControllerAnimated:YES];
}
You need to make use of custom delegates. Create a protocol in your detailview and implement it in your rootview.Pass the selected string as parameter to delegate method and from the delegate method, display it in your textfield.
//something like this
#interface detailViewController
// protocol declaration
#protocol myDelegate
#optional
-(void)selectedValueIs:(NSString *)value;
// set it as the property
#property (nonatomic, assign) id<myDelegate> selectedValueDelegate;
// in your implementation class synthesize it and call the delegate method
#implementation detailViewController
#synthesize selectedValueDelegate
// in your didselectRowAtIndex method call this delegate method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self selectedValueDelegate])selectedValueIs:valueString] ;
[self.navigationController popViewControllerAnimated:YES];
}
#end
// In your rootViewController conform to this protocol and then set the delegate
detailViewCtrlObj.selectedValueDelegate=self;
//Implement the delegate Method
-(void)selectedValueIs:(NSString *)value{
{
// do whatever you want with the value string
}
Hi you will have to do it using protocols and delegate
Please see my linkon protocol and delegate
you can also do it by creating a variable in appdelegate , setting its property and accessing it in any other view .
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
delegate.yourVariable;

Inserting data from one table to another table

I have two UITableViewController classes, MainTableController and SubTableController.
From AppDelegate class I am calling MainTableController class.
At first this class is empty, and there is button named "show list" in this class.
When I click on this button I will go to SubTableController and there I have a list of actions in form of table.
Now if I choose to first cell action then that action name has to come on my first cell of table in MainTableController. But I am not able to print that name in table of MainTableController class.
In SubTableController:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ActionList * actionListObj = [appDelegate.actionArray objectAtIndex:indexPath.row];
self.chooseActions = actionListObj.actionName;
MainTableController * mainViewController = [[MainTableController alloc] init];
[mainViewController getAction:self.chooseActions];
[self.navigationController dismissModalViewControllerAnimated:YES];
}
In MainTableController:
-(void) viewWillAppear:(BOOL)animated{
[self reloadData];
}
-(void) reloadData{
[self.myTableView reloadData];
}
-(void) getAction: (NSString *) actionChoose{
self.action = actionChoose;
[self reloadData];
}
-(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] autorelease];
}
// Configure the cell...
cell.textLabel.text = self.action;
return cell;
}
When I debug, in MainTableController I am getting the action in getAction method but in table cell text string is null.
Can anyone please help me regarding this?Where am I going wrong?
You are allocating and initializing a new view controller each time you select a cell in SubTableController.
MainTableController * mainViewController = [[MainTableController alloc] init];
and of course, it isn't the one in place in the navigation stack.
You need to make these two controllers communicate.
I suggest that the sub view controller define a property on the main one, in order to message it when needed.
In SubTableController, add a property and synthesize it :
#property(readwrite, assign) MainViewController *mainViewController;
// and ...
#synthesize mainViewController;
Of course when you push the sub view controller, don't forget to set the property.
// in main view controller
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// alloc/init the sub VC
subVCInstance.mainViewController = self;
[self pushViewController:subVCInstance ......
Now when a row is selected in the sub one, message the main one, without alloc/init a new MainViewController object :
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ActionList * actionListObj = [appDelegate.actionArray objectAtIndex:indexPath.row];
self.chooseActions = actionListObj.actionName;
//MainTableController * mainViewController = [[MainTableController alloc] init];
[self.mainViewController getAction:self.chooseActions];
[self.navigationController dismissModalViewControllerAnimated:YES];
}
This should work just fine.
In didSelectRowAtIndexPath of the SubTableController class, you are allocating new MainTableController to send the data.
MainTableController * mainViewController = [[MainTableController alloc] init];
[mainViewController getAction:self.chooseActions];
You should not do like that. Because the existing mainview will be different from the newly allocated one. You should use delegate to give back the data. For more info on Protocols and delegates, see here
More example here

Pushing viewController from a tableview that is inside a viewController not working

I am having an issue pushing my view controller from a tableview that was dropped into a viewController, and not a TableViewController.
I have found a thread on here with a solution here
pushViewController is not pushing
The problem is.. I have done his solution and my view still does not push. I have connected my tableview via ctrl+drag to the view controller and set both the dataSource and delegate. In the post i mentioned, they say the solution was to 'create a referencing outlet from the tableview to the view controller.' But I don't exactly know what that means. So help with that would be good as well. I have followed this tutorial and am stuck on step 9 obviously.
The line of code not triggering is
[self.navigationController pushViewController:facility animated:YES];
My code is as follows...
viewTable methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"list Size: %#",list);
return [list count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
CustomerListData *customer = [self.list objectAtIndex:indexPath.row];
cell.textLabel.text = customer.facilityName;
// cell.textLabel.text = #"Detail";
return cell;
}
-(void)setValue:(NSMutableArray*)array
{
//NSMutableArray *newArray = [[NSMutableArray alloc] init];
list = array;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
FacilityMissionListViewController *facility = [self.storyboard instantiateViewControllerWithIdentifier:#"facilityMissionList"];
[self.navigationController pushViewController:facility animated:YES];
//UINavigationController* navController = self.navigationController;
}
the very last commented out line is there to check if navigationcontroller was null. It is not.
From what I have gathered the issue here lies in the fact the table view is inside the view controller and its not a "tableviewcontroller." This method apparently works if that is the case, but some other steps must be taken if not.. but I don't know them.
Thanks in advance.
It sounds like your NavigationController is not set up correctly. Could you post the code that sets it up?
Put a :
NSLog(#"%#", self.navigationController);
in your didSelectRowAtIndexPath method and you'll see if the method is being called and if the navigationController is nil. It might be one of this cases.
Otherwise make sure that the FacilityMissionListViewController is not nil either.