0

I know it's a commom problem but the cellForRowAtIndexPath: is not called when I use [actionTableView reloadData];. I already linked dataSource and delegate thanks to the storyboard but it doesn't solve the issue.

Here's a part of my code:

SearchViewController.h

#import <UIKit/UIKit.h>

@interface SearchViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchDisplayDelegate>

@property (strong, nonatomic) IBOutlet UITableView *actionTableView;
@property (strong, nonatomic) IBOutlet UISearchBar *actionSearchBar;
@property (strong, nonatomic) NSMutableArray *actionsArray;
@property (strong, nonatomic) NSMutableArray *filteredActionArray;

@end

SearchViewController.m

#import "SearchViewController.h"
#import "Action.h"

@interface SearchViewController ()

@end

@implementation SearchViewController

@synthesize actionsArray, actionTableView, filteredActionArray, actionSearchBar;

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [filteredActionArray count];
    } else {
        return [actionsArray 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];
    }

    NSLog(@"Aloha");

    // Create a new Action object
    Action *a = nil;

    if (tableView == self.searchDisplayController.searchResultsTableView) {
        a = [filteredActionArray objectAtIndex:indexPath.row];
    } else {
        a = [actionsArray objectAtIndex:indexPath.row];
    }

    // Configure the cell
    cell.textLabel.text = a.nomAction;
    [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
    return cell;
}

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
    // Update the filtered array based on the search text and scope.
    // Remove all objects from the filtered search array
    [self.filteredActionArray removeAllObjects];
    // Filter the array using NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.nomAction contains[c] %@",searchText];
    filteredActionArray = [NSMutableArray arrayWithArray:[actionsArray filteredArrayUsingPredicate:predicate]];
}

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    // Tells the table data source to reload when text changes
    [self filterContentForSearchText:searchString scope:
     [[self.searchDisplayController.searchBar scopeButtonTitles]objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    // Tells the table data source to reload when scope bar selection changes
    [self filterContentForSearchText:self.searchDisplayController.searchBar.text scope:
     [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

As you see I also use a searchBar to filter the array, but w/o this it doesn't work either.

EDIT: SPECIFICATION OF THE PROBLEM: reloadData works only if I call it within the viewController. Not if I call it from another viewController. Obviously for the two cases I call the same function updatingTableView located in the viewcontroller where the tableView is. Any ideas to reload the tableView from anotherViewController?

SearchViewController.m (works)

-(IBAction)update{
    [self updatingTableView:nil];
}

-(void)updatingTableView:(NSData*)someData {
   actionsArray = [NSArray arrayWithObjects:@"item1", @"item2", @"item3", nil];
   [actionTableView reloadData];
}

AnotherViewController.m (does not work)

-(IBAction)updateFromElsewhere{
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main"
                                                         bundle: nil];

    SearchViewController *searchViewController = (SearchViewController*)    [mainStoryboard
                                                             instantiateViewControllerWithIdentifier: @"searchcontroller_id"];

    [searchViewController updatingTableView:nil];

}

NB: I can pass some data from a view controller to the other without problem here.

romain64
  • 89
  • 9
  • 1
    Make sure your `tableView: numberOfRowsInSection` are not returning 0 – teamnorge Jul 19 '15 at 17:15
  • `numberOfSectionsInTableView` and `numberOfRowsInSection` are not even called – romain64 Jul 19 '15 at 17:40
  • then your view controller is not listening to UITableViewDelegate, I am not sure how you connected them in Storyboard. But if you 100% sure you made everything right and if it fits your project you can implement `awakeFromNib` method where you put `actionTableView.delegate = self` – teamnorge Jul 19 '15 at 17:47
  • Yeah everything is well connected. It doesn't work with `awakeFromNib` either. `numberOfSectionsInTableView` and `numberOfRowsInSection`are only called once when the app is opening but at this moment the array is empty. Then when I use an IBAction to load data into the NSArray and then process `reloadData` they are not called anymore. – romain64 Jul 19 '15 at 17:56
  • to force calling `numberOfRowsInSectionare` and `numberOfSectionsInTableView` you can put your reload data inside `[tableView beginUpdates]; [tableView reloadData]; [tableView endUpdates];` in general it's not necessary if you do not delete / insert cells, but just as a workaround to understand what's wrong. – teamnorge Jul 19 '15 at 18:02
  • please also check if your dataSource is properly connected "File's Owner". And if even this does not help I would suggest removing tableView from your storyboard add the new one and start doing everything from scratch. – teamnorge Jul 19 '15 at 18:09
  • It doesn't change anything with `beginUpdates` and `endUpdates`. Yes I will start everything from scratch. I have another project with exactly the same code and where it works, that's strange. – romain64 Jul 19 '15 at 18:24

3 Answers3

1

One thing I always run into when struggle up a table view is connecting the table with the interface using interface builder. But when you call [actionTableView reloadData] without having the connection made to the table, nothing will happen.

I ways forget that super simple step. Hope this helped

ErickES7
  • 558
  • 6
  • 16
  • I verified it at least ten times! The `actionTableView` outlet, `delegate` and `dataSource` are all connected with IB – romain64 Jul 19 '15 at 18:05
  • Dang! Okay, And you know the methods are not being called bc you have say a breakpoint?? How do you know they're not being called??? – ErickES7 Jul 19 '15 at 18:07
  • Nice, Umm try assigning the delegate and data source promgromarically, like in the viewDidAppear: then call reloadData in the code right after, in case something went wrong in the story board – ErickES7 Jul 19 '15 at 18:11
  • It doesn't work programmatically with `actionTableView.delegate = self` and `actionTableView.dataSource = self`. I really don't know what's wrong – romain64 Jul 19 '15 at 18:41
  • I got nothing. I looked in this link briefly but don't see much difference bc I only work on xib not so much in story boards. Maybe the answer will be a missing step?? http://www.appcoda.com/uitableview-tutorial-storyboard-xcode5/ – ErickES7 Jul 19 '15 at 18:53
  • The initialization is working but I still get stuck updating it with `reloadData` – romain64 Jul 19 '15 at 21:34
0

The problem is you never initialize actionsArray and filteredActionArray to be non-nil. As a result, numberOfRowsInSection always returns 0, so cellForRowAtIndexPath won't be called.

Dklionsk
  • 203
  • 1
  • 5
  • Before calling `reloadData` actionsArray is loaded with another function not shown here. And before reloading the data I check the content of the NSArray and everything is ok – romain64 Jul 19 '15 at 18:02
  • This is super strange, so numberOfSectionsInTableView: is never called? You've placed a breakpoint **on the function header** and nothing? Bc any table view that had their data source attached to anything will load its data automatically upon loading the view, it should call these functions at least once – ErickES7 Jul 19 '15 at 21:19
0

Finally found the solution!

In SearchViewController.m where the tableView is, put this in viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatingTableView) name:@"reload_data" object:nil];

With still:

-(void)updatingTableView{
    [actionTableView reloadData];
}

In AnotherViewController.m

[[NSNotificationCenter defaultCenter] postNotificationName:@"reload_data" object:self];

how to reload tableview of another uiviewcontroller in current viewcontroller

Thanks everyone!

Community
  • 1
  • 1
romain64
  • 89
  • 9