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
1
  • 3
    Think about it twice. The networking operation is asynchronous. And this question is a duplicate. Commented Sep 20, 2013 at 18:35

2 Answers 2

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.
Sign up to request clarification or add additional context in comments.

4 Comments

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, 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.
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.
: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.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.