3

I need to set my UITableView delegate and datasource from a separate class (data ready after parsing called by a method), but every time my table is emtpy. I'm using ARC and this is simplified code:

//HomeViewController.h

#import <UIKit/UIKit.h>
#import "TableController.h"

@interface HomeViewController : UIViewController {

    IBOutlet UITableView *table;
    TableController *tableController;
}

@end

and

//HomeViewController.m

#import "HomeViewController.h"

@interface HomeViewController ()

@end

@implementation HomeViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    tableController = [[TableController alloc] init];
    table.dataSource = tableController.tableSource.dataSource;
    table.delegate = tableController.tableSource.delegate;
    [tableController loadTable]; // HERE I CALL LOADTABLE FROM TABLECONTROLLER CLASS TO PARSE DATA AND POPULATE UITABLEVIEW
    [table reloadData];

}

and

// TableController.h

#import <UIKit/UIKit.h>

@interface TableController : NSObject <UITableViewDelegate, UITableViewDataSource> {

   UITableView *tableSource;

   // a lot of NSMutableArray to parse my data

}

- (void)loadTable;

@property (nonatomic, strong) UITableView *tableSource;

@end

and

//TableController.m

#import "TableController.h"
#import "AFNetworking.h"

@interface TableController ()

@end

@implementation TableController

@synthesize tableSource;

- (void)loadTable {

    NSURL *parseURL = // remote URL to parse Data
    NSURLRequest *request = [NSURLRequest requestWithURL:parseURL];
    AFJSONRequestOperation *parseOperation = [AFJSONRequestOperation
                                               JSONRequestOperationWithRequest:request
                                               success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

                                                   // code to parse Data and NSLog to test operation

                                                   [tableSource reloadData];
                                                   [tableSource setUserInteractionEnabled:YES];
                                                   [tableSource scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

                                               }
                                               failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
                                                   NSLog(@"%@", [error userInfo]);
                                               }];
    [parseOperation start];
    [tableSource setUserInteractionEnabled:NO];
}

and, obviously, still in TableController.m, all the classic UITableView delegate methods:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// my code
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// my code
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// my code
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
// my code
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// my code
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// my code
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// my code
}

Well, the parse is perfect (I can test it with a NSLog), but my table is empty. Can u help me?

EDIT: In my code loadTable parsing method is asynchronous, so table load with right datasource and delegate but BEFORE all data is parsed; in fact IF I SET a fixed numberOfRows and then SCROLL TABLE I can see all the rows populated. But, when I load HomeViewController, *table is still EMPTY.

SILminore
  • 509
  • 3
  • 10
  • 28
  • Is numberOfSectionsInTableView getting invoked? If not, you probably failed to properly set the dataSource property, or reloadData was never executed. (Does tableController.tableSource.dataSource actually return anything?) – Hot Licks Mar 14 '13 at 11:25
  • Its all invoked, if I put a UITableView INTO TableController (like a ViewController) it is not empty, but tableController.tableSource.dataSource actually return NULL – SILminore Mar 14 '13 at 11:26
  • Did you try table = tableController.tableSource; ?? – Jeremy Mar 14 '13 at 11:29
  • @Jeremy I can't try it, I get error "unrecognized selector sent to instance..:" – SILminore Mar 14 '13 at 11:34
  • Hm ok, i don't know then. Did you link the tableview from the xib file / storyboard view to your tableview in your header file? Also did you link the delegate/dataSource in the xib file / storyboard view to the view controller? – Jeremy Mar 14 '13 at 11:40
  • Huh, but I DONT WANT to link delegate/dataSource in the storyboard view to my ViewController (HomeViewController), I WANT to get UITableView delegate/dataSource from a separate class (TableController)! – SILminore Mar 14 '13 at 11:43
  • If you're getting no data it's probably because one of the dataSource methods is telling the TableView that there is no data. Is cellForRowAtIndexPath getting called? – Hot Licks Mar 14 '13 at 12:16
  • @HotLicks, see my EDIT: @arun.s get the point: In my code the `loadTable` parsing method is asynchronous, so my table is loaded with right datasource and delegate but BEFORE all data is parsed; in fact IF I SCROLL TABLE I can see all the rows populated, as I expected. Im still searching a way to get table populated WHEN I LOAD HOMEVIEWCONTROLLER... – SILminore Mar 14 '13 at 13:26

1 Answers1

7

From where/How you are setting UITableView *tableSource object in your TableController ?

Also try reloading tableview in main thread.

Edit

Change these in your HomeController viewDidLoad

   table.dataSource = tableController.tableSource.dataSource;
   table.delegate = tableController.tableSource.delegate;

to

   table.dataSource = tableController;
   table.delegate = tableController;

Also get set HomeController class as delegate of TableController & once you get the response . Call a method in HomeController to reload the tableview (in main thread)!!!

For that first create a property parent in your TableController .h file like this

@property(nonatomic,retain) id parent;

Then set the HomeController as the delegate from HomeController viewDiDLoad like

tableController.parent = self.

Once you get response in completion block call,

[self.parent reloadTableView]; // reloadTableView will be a function in the HomeController that is having [self.table reloadData].

Hope this will fix the issue.

arun.s
  • 1,528
  • 9
  • 12
  • I have tried to add this code in HomeViewController ViewDidLoad: `NSLog(@"TABLE: %@",tableController.tableSource);` and result is NULL – SILminore Mar 14 '13 at 11:56
  • Thank you, @arun.s, you get the point! In my code the `loadTable` parsing method is asynchronous, so my table is loaded with right datasource and delegate but BEFORE all data is parsed; in fact IF I SCROLL TABLE I can see all the rows populated. Unluckly your code doesnt work and the table is still empty... – SILminore Mar 14 '13 at 13:24
  • But you are making userInteractionEnabled to NO while u start parsing right ? . Also I have tested the code (yours & mine combined) with dummy datasource & it was working fine. – arun.s Mar 14 '13 at 13:39
  • Yes, but userInteractionEnabled can be YES or NO, problem is that I cannot call `[table reloadData]` right after the end of parsing. In fact if I manually RELOAD with a method (or SCROLL) table is perfect.. – SILminore Mar 14 '13 at 13:55
  • For that only we are setting HomeController as the delegate of TableController so that you can call like this [self.parent reloadTableView]; and HomeController will be having reloadTableView function in it like i mentioned in the EDITED POST. – arun.s Mar 14 '13 at 13:57
  • Thank you very much, @arun.s, I have tried and tried your code and finally I found the issue (it was my typo error): so your solution is accepted :) – SILminore Mar 14 '13 at 14:08