Search code examples
iosuitableviewnsmutablearraynsurlnsurlrequest

NSArray is empty after sending data from my class to TableViewController


I have a Data class that inherits from NSObject.
In this class I handle my data requests.
After this I want to send the data that it holds in an NSMutableArray to my UITableViewController.

How can I fix this?

@interface Data : NSObject

@property(nonatomic,strong) NSMutableArray *data;

-(NSMutableArray *) loadData;

-(id)init;

@end


@implementation Data

@synthesize data;

-(id)init {

    self = [super init];

    if(self){
        self.data = [[NSMutableArray alloc]init];
    }

    return self;

}

- (NSMutableArray *)loadData {


    NSString *url = @"http://localhost/xampp/flashbackapi/";

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {


        [data addObject:responseObject];


    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error %@",error);
    }];

    return data;

}

@end


#import <UIKit/UIKit.h>
#import "Club.h"
#import "Data.h"

@interface ClubsTableViewController : UITableViewController

@property(nonatomic,strong) Data *holderData;
@property(nonatomic,strong) NSMutableArray *teams;



@end

#import "AFNetworking.h"

@implementation ClubsTableViewController


    - (void)viewDidLoad
    {
        [super viewDidLoad];

        self.holderData = [[Data alloc]init];
        self.teams = [[NSMutableArray alloc]init];

        self.teams = self.holderData.loadData;

        NSLog(@"%@",self.teams); //this array is empty.. why? 



    }

Solution

  • Your loadData method is returning a data property that will never contain the contents of your responseObject. This is because your loadData method contains an asynchronous call (to manager GET:parameters:success:). When the asynchronous call returns, the data property/ivar is being populated, which, in your case is far too late. One solution would be to make loadData an asynchronous method too.

    So, something like:

    - (void)loadDataWithCompletionBlock:(void (^)(NSMutableArray *data))completionBlock {
    
        NSString *url = @"http://localhost/xampp/flashbackapi/";
    
        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    
    
            [data addObject:responseObject];
            completionBlock(data);
    
    
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Error %@",error);
            // TODO: Return completionBlock with empty array (or error?)
        }];
    };
    

    Invoked like this:

    ClubsTableViewController __weak *weakSelf = self; 
    [self loadDataWithCompletionBlock:^(NSMutableArray *data) {
        weakSelf.teams = data;
    }];
    

    Also, you don't seem to be using the NSMutableArray as an array as it seems that it will always only contain one element.