【问题标题】:__block : Assigning a variable inside a block to an outside variable does not work__block :将块内的变量分配给外部变量不起作用
【发布时间】:2013-09-26 05:49:34
【问题描述】:

根据here 的建议,我编写了以下代码:

__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;

问题是该方法返回null。

你能帮帮我吗? 谢谢。

新代码,至少app不会崩溃。

#import <Foundation/Foundation.h>

@interface LOArticulos : NSObject

@property (strong,nonatomic)NSArray *todosLosArticulos;

+ (LOArticulos *)sharedInstance;

-(void)loadArticlesFromJSON;

@end

实施:

#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

【问题讨论】:

  • 三思而后行。网络操作是异步的。这个问题是重复的。

标签: ios automatic-ref-counting objective-c-blocks weak-references


【解决方案1】:

您的代码实际上有两个问题会导致articlesArray 为nil。

  1. 返回articlesArray 时,异步操作很可能未完成。这已经说明了。
  2. 您已将articlesArray 声明为弱指针。从概念上讲,这意味着“仅当有人 else 强烈提及它时才将其保留在内存中”。完成块结束后,文章将超出范围,因此articlesArray 将设置为 nil。

【讨论】:

  • 是的,你说得对,我现在可以看得很清楚了。我正在寻找如何解决它,也许重写方法。如果我想在一个块中分配一个变量,我必须声明它是弱的。
  • Luis,没有规定必须将块变量声明为弱变量。但是,将块中使用的变量声明为弱变量是一个常见的建议,因为否则很容易使用块变量创建保留循环。在块中引用 self 时尤其如此。
  • 在您的情况下,我可能让调用者传入一个以 NSArray 作为参数的完成块。当网络操作完成时,您可以通过调用完成块将 'articles' 传回给调用者,并完全摆脱 'articlesArray'。
  • :恐怕我不知道。我能够将 JSON 从块中取出到另一个方法并提取数组,但没有别的。我尝试了 NSOperationQueue 但我无法实现该解决方案。我已经用新代码更新了我的 OP。
【解决方案2】:

为了扩展 H2C03 所说的内容,我认为您的方法在异步操作完成之前返回,因此articlesArray 的值仍然为 nil。

【讨论】:

    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-27
    • 2016-10-10
    • 2020-12-12
    • 2018-03-13
    相关资源
    最近更新 更多