UITableViewController reloadData cellForRowAtIndexPath not being called - ios

called loadData method from other viewcontoller like:
TestTVC *testTVC = [[TestTVC alloc] init];
[testTVC loadData];
I put NSLog(#"testTVC Array section:%lu has %lu rows ") in numberOfRowsInSection, it return result.
However in the cellForRowAtIndexPath section, the NSLog(#"cellForRowAtIndexPath") never printed for somehow.
I was sure that my delegate and data source were set properly. Because it works when [self loadData]
I also try run it in the main thread, it does't work.
Does anyone knows? Thanks.
updated: i used [self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone]; instead of [self.tableView reloaddata], it works but it didn't reload the UIImages in table cell.
NSLog(#"change cell image to testTVCImg1");
[testTVCCell.selectImgView setImage:[UIImage imageNamed:#"testTVCImg1"]];
the NSLog debug message printed, but the image didn't changed.

cellForRowAtIndexPath is called when a cell become visible.
When you do
TestTVC *testTVC = [[TestTVC alloc] init];
[testTVC loadData];
testTVC is not in the view hierarchy and its tableview neither. So cellForRowAtIndexPath won't be call.

Related

Objective-C deselectRowAtIndexPath is kinda working

In my cellForRowAtIndexPath and I pre selecting a row:
NSArray *tempArray = [[communityPrefs objectForKey:#"Community"] componentsSeparatedByString:#","];
NSMutableArray *tempArrayMutable = [[NSMutableArray alloc] initWithArray:tempArray];
if ([tempArrayMutable containsObject:cell.textLabel.text])
{
[selectedAreaTable selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
This part works great. However the selected item is at the bottom of the page and the user will not see it, but when they scroll down to that cell it is selected.
Now I am trying to write a piece of code the will deselect all selected cells like so:
for(NSIndexPath *index in selectedAreaTable.indexPathsForSelectedRows)
{
if(index.row != 0)
{
[selectedAreaTable deselectRowAtIndexPath:index animated:NO];
}
}
but after I run this code the cell at the bottom is still selected. So my question is, why is this cell not being deselected? Is it because its not there until you scroll to it? How can I fix this problem?
Is it because its not there until you scroll to it?
Yes. I believe that you should change "selected" state using cell objects only for visible rows. All other rows should retrieve "selected" status in cellForRowAtIndexPath method
user979331,
you dont have to remove the selection in seperate method rather you can handle that too in cellForRowAtIndexPath as well.
You can declare the array NSMutableArray *tempArrayMutable as a property,
when you want to deselect all cell lets assume a method named clear all selection
-(void)clearAllSelection {
[self.tempArrayMutable removeAllObjects];
self.tableView reloadData];
}
Finally in cellForRowAtIndexPath change as
if ([self.tempArrayMutable containsObject:cell.textLabel.text])
{
[selectedAreaTable selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
else{
[selectedAreaTable deselectRowAtIndexPath:indexPath animated:NO];
}

UITableView reloadData is not working in iOS

I'm creating the UITableView datasource array using this code:
-(void) viewWillAppear:(BOOL)animated
{
// IBOutlet of tableview is 'editMsgTableView'
editMsgTableView.dataSource=nil;
editMsgTableView.delegate=nil;
menuMessageArray = [[NSMutableArray alloc] init];
editMainMenuMsgArray = [[NSMutableArray alloc] init];
menuMessageArray = [DBManager fetchmenu:0 noOfRows:32];
for(int i=0; i< [menuMessageArray count]; i++)
{
NSMutableDictionary *menuMsgListDic = [[NSMutableDictionary alloc] init];
menuMsgListDic = [menuMessageArray objectAtIndex:i];
[editMainMenuMsgArray addObject:menuMsgListDic];
}
editMsgTableView.dataSource=self;
editMsgTableView.delegate=self;
[editMsgTableView reloadData];
}
But it works for the first time. But whenever I do some tableView editing stuff or comes from another view controller,after that if viewWillAppearis called then reloadData is not working. I also tried:
dispatch_sync(dispatch_get_main_queue(), ^{
[editMsgTableView reloadData];
});
but not working. Please help me out.
When editing begins call [tableView startUpading]; and when editing is done, call [tableView stopUpdating]; then [tableView reloadData];.
Try ,
dispatch_async(dispatch_get_main_queue(), ^{
[editMsgTableView reloadData];
});
are you giving to that viewController the tableViewDelegates correctly? :
#interface theNameOfTheViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> in the .h file?
i suggest not to do this:
editMsgTableView.dataSource=nil;
editMsgTableView.delegate=nil;
editMsgTableView.dataSource=self;
editMsgTableView.delegate=self;
just this:
[self.editMsgTableView reloadData];
be sure that all the delegate methods are called when you use reloadData (put a breakpoint in every delegate method that should be used to reload the Data of the table when you make a change or the view Appears), remember that reloadData method, calls all delegate methods (if you´re giving to the view controller correctly the delegate as I said before) of the tableViewController. If nothing of this helps you, tell me.
I am assuming that you are navigating the view from one view to another view, then you should call [tableView reloadData] on ViewDidLoad.
This is because of the view life cycle - when you are coming back from one view and your tableView data source is updated, the view life cycle will be like this:
viewDidLoad
tableViewDelegateMethods
viewDidAppear
So when you update tableView's data source object and call reloadData during viewDidLoad will resolve the issue.

Issue reloading cellForRowAtIndexPath calling from a method in another class - Objective C

I have the following method within a ViewController class:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:
(NSIndexPath *)indexPath
{
UITableViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
NSInteger tag = cell.tag;
// SEND TO SINGLE NEWS FEED TO DISPLAY THE INFORMATION OF THE VIDEO
singleNewsFeed* myScript = [[singleNewsFeed alloc] init];
[myScript startProcess:tag];
[self performSegueWithIdentifier:#"moveToSingleData" sender:self];
}
The receiver class:
- (void)startProcess:(NSInteger)number {
NSInteger check = number;
singlecellID = check;
// MAKE REQuEST TO SERVER
[self makeRequests];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
So what happens is that makeRequests runs and the tableView is refreshed. All methods for the tableView run except the cellForRowAtIndexPath
Here is the thing I know that all of these work properly because I have the same exact classes doing the same exact thing except they are sub viewcontrollers of a parent viewcontroller. I had the same exact issue and used self.parentViewController.childViewControllers[1]; to fix that when calling the method and it worked perfect. But this is different because this is a completely separate ViewController. So therefore I am not sure what to use to call that ViewController that allows cellForRowAtIndexPath to work correctly.
Suggestions, thoughts?
David
You're calling [self.tableView reloadData] but I don't think object you're calling it from is your table view controller. No?

Row deletion does not refresh table view in ios app

I have spent hours searching for the solution with out any luck. I am trying to delete a row (also deselect same row) programmatically. After row deletion call below, UITableViewDelgate methods get called expectedly and data source is updated but UITableView is not refreshed. deselectRowAtIndexPath call also does not work. I tried all kinds of scenarios as shown by commented lines.
Here is my code:
checkoutPerson is called as a result of observer listening for NSNotificationCenter messages.
- (void) checkoutPerson: (NSNumber*) personId {
Person *person = [_people objectForKey:personId];
if( person )
{
// Remove person from data source
int rowIndex = person.rowIndex;
S2Log(#"Deleting row number=%d", rowIndex);
[_allKeys removeObjectAtIndex:rowIndex];
[_people removeObjectForKey: personId];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:0];
//[[self tableView] beginUpdates];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
S2Log(#"Deleting indexPath row=%d", [indexPath row]);
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
//[[self tableView] endUpdates];
S2Log(#"Reloading data");
//[[self tableView] reloadData];
//[self performSelector:#selector(refreshView) withObject:nil afterDelay:1.5];
//[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}
}
I will appreciate for help.
Thanks
-Virendra
I believe deleted cell is not being recycled. If I delete row in the middle, last row is always erased (since there is one less item) but the deleted row remains.
Use the above code between two function for table view
[tableView beginUpdates];
// the deletion code from data source and UITableView
[tableView endUpdates];
By calling this functions you are telling UITableView that you are about to make updates for deleting your cell.
Edit
The other problem I see with your code is you first delete the data from the data source.
Now you are asking for the UITableViewCell (which actually reloads the UITableView)
and then you are deleting the row from UITableView
I guess you should fetch the UITableViewCell before deleting values from your data source.
I found the problem. It has nothing to do with the code I posted above. It is syncing problem between visual display and the contents of data source. I have an embedded UITableView as part of a composite view. In composite view's controller, I was wiring up UITableView's delegate and data source to an instance of UITableViewController. Instead of this, I should have set UITableViewController's tableView property to the embedded UITableView. It seems that UITableView has to be contained within UITableViewController in order to correctly sync up table view visual display to the contents of data source. This also fixes row deselection and scrolling. I also needed to delay reloadData call in which case deleteRowsAtIndexPaths:withRowAnimation is not required. All you need is to modify the contents of your data source and call reloadData with a delay of 1.5 Seconds.
Thanks to all for great help.

How to load new content into a UITableView using IBAction?

FYI - Noob iOS developer here.
My current setup is a UIViewController with a UIView within, then a UITableView within the UIVIew. So it goes like this...
UIViewController --> UIView --> UITableView
The reason for this is because I have other elements wrapped with the tableview. The UIViewController loads dynamic content into the table view. I have a segmented Control in which I want to use to switch the content within the table view.
I've read something on [table reload] and [table beginUpdate] but don't understand how to use it. Any help would be great.
You need to implement a method for UIControlEventValueChanged event ofUISegmentedControl for this.
[yourSegmentedControl addTarget:self action:#selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
And implement the segmentChanged method like:
- (void)segmentChanged:(id)sender
{
UISegmentedControl *mySegment = (UISegmentedControl *)sender;
switch ([mySegment selectedSegmentIndex])
{
case 1:
//load first contents
break;
case 2:
//load second contents
break;
default:
break;
}
[self.yourTableView reloadData];
}
Ok, so [table reloadData] will reload the data (so if you change the data and want to update the table with the necessary data call this), but straight after you call that make sure to call [table setNeedsDisplay] to refresh the UI.[table beginUpdates]
begins a series of method calls that insert, delete, or select rows and sections of the receiver. You end the processes with [table endUpdates];
Make sure you set your table view's dataSource and delegate to self, this can be done through the xib and programmatically like this:
[table setDelegate: self];
or
[table setDataSource: self];
As said:
Call this delegate method for UISegmentedControl
- (void)segmentedControl:(UISegmentedControl*)segmentedControl didSelectIndex:(NSUInteger)selectedIndex
{
if(selectedIndex == 0)
{
// Update the data
}
else if(selectedIndex == 1)
{
// Update the data
}
[table reloadData];
[table setNeedsDisplay];
}
For example,
Your UIView named *myView and your UITableView named *myTableView,
the time you want to reload tableview, in your UIViewController , you should reload tableview like this:
[self.myView.myTableView reload];
and make sure tableview's delegate and dataSourceDelegate is set correctly.
Need to set the delegate & data source for tableview in ViewController.h file like
UITableViewDataSource, UITableViewDelegate.
Implement delegate & datasource methods in ViewController.m file
[tableview SetDelagate:self];
[tableview SetDatasource:self];
Implement the delegate methods.
And reload the table using
[tableView reloadData];
method.

Resources