0

following the recommendations found here, I wrote the following piece of code:

__weak __block NSMutableArray *articlesArray = nil; // I'm using ARC
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.xente.mundo-r.com/turkish/json/lakari.json"]];

    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:@"http://www.xente.mundo-r.com/turkish/json/lakari.json"
                                                      parameters:nil];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        // Print the response body in text

        NSData *data = [NSData dataWithData:responseObject];
        NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        NSMutableArray *articles = [[NSMutableArray alloc]initWithCapacity:jsonArray.count];

        for (NSDictionary *articleDictionary in jsonArray) {
            LOArticulo *articulo = [[LOArticulo alloc]init];
            articulo.ID = articleDictionary[@"id"];
            articulo.marca = articleDictionary[@"marca"];
            articulo.modelo = articleDictionary[@"modelo"];
            articulo.price = articleDictionary[@"precio"];
            articulo.categoria = articleDictionary[@"categoria"];
            articulo.photoURL = articleDictionary[@"photoUrl"];
            [articles addObject:articulo];
        }

        articlesArray = articles; 

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

    return articlesArray;

The question is that the method returns null.

Could you please help me? Thank you.

New code, at least app does not crash.

#import <Foundation/Foundation.h>

@interface LOArticulos : NSObject

@property (strong,nonatomic)NSArray *todosLosArticulos;

+ (LOArticulos *)sharedInstance;

-(void)loadArticlesFromJSON;

@end

Imlementation:

#import "LOArticulos.h"
#import "LOArticulo.h"
#import "AFNetworking.h"

@interface LOArticulos (){
    NSArray *articlesArray;
}
@property (nonatomic,strong) NSArray *articlesArray;

@end

@implementation LOArticulos
@synthesize articlesArray;

+(LOArticulos *)sharedInstance{
    static LOArticulos *_sharedArticles;

    static dispatch_once_t once;
    dispatch_once(&once, ^{
        _sharedArticles = [[LOArticulos alloc]init];
    });
    return _sharedArticles;
}
-(id)init{


    if (self = [super init]) {
        [self loadArticlesFromJSON];
        self.todosLosArticulos = articlesArray;

    }
    return self;
}

- (void)getJson:(id)jsonObject{
    self.articlesArray = [NSArray new];

    NSData *data = [NSData dataWithData:jsonObject];
    NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    NSMutableArray *articles = [[NSMutableArray alloc]initWithCapacity:jsonArray.count];
    for (NSDictionary *articleDictionary in jsonArray) {
        LOArticulo *articulo = [[LOArticulo alloc]init];
        articulo.ID = articleDictionary[@"id"];
        articulo.marca = articleDictionary[@"marca"];
        articulo.modelo = articleDictionary[@"modelo"];
        articulo.price = articleDictionary[@"precio"];
        articulo.categoria = articleDictionary[@"categoria"];
        articulo.photoURL = articleDictionary[@"photoUrl"];
        [articles addObject:articulo];
    }
    self.articlesArray = [articles copy];
}

-(void)loadArticlesFromJSON{

    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.xente.mundo-r.com/turkish/json/lakari.json"]];

    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:@"http://www.xente.mundo-r.com/turkish/json/lakari.json"
                                                      parameters:nil];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        [self getJson:responseObject];

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

@end
Community
  • 1
  • 1
Luis
  • 447
  • 1
  • 7
  • 24
  • 3
    Think about it twice. The networking operation is asynchronous. And this question is a duplicate. –  Sep 20 '13 at 18:35

2 Answers2

4

There are actually two issues with your code that will result in articlesArray being nil.

  1. The asynchronous operation is most likely not completed when you return articlesArray. This has already been stated.
  2. You've declared articlesArray as a weak pointer. Conceptually, this means "only keep this around in memory if somebody else refers to it strongly". After your completion block ends, articles will go out of scope and so articlesArray will be set to nil.
Jonathan Arbogast
  • 9,620
  • 4
  • 35
  • 47
  • yes, you're right, I can see it clearly now. I'm searching how to solve it, maybe rewriting the methods. If I want to assign a variable inside a block, I have to declare it weak. – Luis Sep 21 '13 at 14:16
  • Luis, There is no rule that says you have to declare a block variable as weak. However, declaring variables used within a block as weak is a common suggestion because otherwise its easy to create a retain cycle with block variables. This is especially true when referencing self within a block. – Jonathan Arbogast Sep 23 '13 at 12:41
  • In your situation, I might have the caller pass in a completion block that has an NSArray as a parameter. When the network operation completes, you could pass 'articles' back to the caller by calling their completion block and get rid of 'articlesArray' entirely. – Jonathan Arbogast Sep 23 '13 at 12:43
  • :I'm afraid that's beyond my knowledge. I was able to get JSON out of the block to another method and extract the array, but nothing else. I tried NSOperationQueue but I couldn't implement the solution. I have updated my OP with new code. – Luis Sep 23 '13 at 21:24
1

To expand on what H2C03 said, what I believe is happening is that your method is returning before the asynchronous operation has completed, therefore the value of articlesArray is still nil.

Senior
  • 2,259
  • 1
  • 20
  • 31