ios - 程序块乱序执行?

ios - Program with block executed out of order?

我正在尝试从我的后端获取一组 url。

我使用 AFNetworking 并且我有一个 HTTPUtil class 作为 singleton 来处理我的请求。

HTTPUtil.m

#import "HTTPUtil.h"

@implementation HTTPUtil

+(instancetype)sharedInstance{
    NSLog(@"sharedInstance");    //to check the order
    static HTTPUtil* manager;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        manager = [[HTTPUtil alloc] init];
    });
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    return manager;
}

-(void)getImageArrayFromURL:(NSString *)url success:(void(^)(NSArray* array))success failure:(void(^)(NSError* error))failure{
    NSLog(@"getting...");    //to check the order
    [self GET:url parameters:nil progress:nil success:^(NSURLSessionDataTask* task, id response){
        NSLog(@"Response: %@", response);
        NSString* imgStr = [[response objectForKey:kResponseDataKey] objectForKey:@"img"];

        //convert nsstring to nsarray
        NSArray* array = [StringUtil arrayFromString:imgStr];

        //construct urls
        NSMutableArray* ret = [[NSMutableArray alloc] init];
        NSMutableString* url;
        for (NSString* rawStr in array) {
            url = [NSMutableString stringWithString:kUrlBase];
            [url appendString:[rawStr stringByReplacingOccurrencesOfString:@"/" withString:@"+"]];
            [ret addObject:url];
        }
        success(ret);
    }failure:^(NSURLSessionDataTask* task, NSError* error){
        NSLog(@"Error: %@", error);
        failure(error);
    }];
}

在我的视图控制器中,我调用了获取数组的方法。

    _vCycleScrollView = [SDCycleScrollView cycleScrollViewWithFrame:CGRectMake(0, 0, 0, 0) delegate:self placeholderImage:[UIImage imageNamed:@"checked"]];
    NSMutableString* url = [NSMutableString stringWithString:kUrlBase];
    [url appendString:@"activityImgArray"];
//
     __block NSArray* imgarr;
    [[HTTPUtil sharedInstance] getImageArrayFromURL:url success:^(NSArray* array){
        imgarr = [NSArray arrayWithArray:array];
    }failure:^(NSError* error){
        NSLog(@"%@", error);
    }];
    NSLog(@"adding...");
    _vCycleScrollView.imageURLStringsGroup = imgarr;

[self.view addSubview:_vCycleScrollView];
[_vCycleScrollView mas_makeConstraints:^(MASConstraintMaker* make){
    make.top.equalTo(self.view);
    make.left.equalTo(self.view);
    make.right.equalTo(self.view);
    make.height.mas_equalTo(180);
    make.width.equalTo(self.view.mas_width);
}];

在控制台中,我得到了

2016-05-20 14:41:19.411 SCUxCHG[10470:4909076] sharedInstance
2016-05-20 14:41:19.415 SCUxCHG[10470:4909076] getting...
2016-05-20 14:41:19.417 SCUxCHG[10470:4909076] adding...
2016-05-20 14:41:19.591 SCUxCHG[10470:4909076] 
Response: {
    data =     {
        img = "[activity/test1, acti/1]";
    };
    message = success;
    result = 0;
}

我认为imgArr 应该在success块中赋值,当我赋值给_vCycleScrollView.imageURLStringsGroup时不应该是nil

但是,我可以从控制台的输出中看出 HTTP 请求是在 NSLog(@"adding..."); 之后发送的,这导致 imgArr 仍然是 nil 当执行 _vCycleScrollView.imageURLStringsGroup = imgarr; 时。

这是为什么?

这就是整个想法:块是乱序执行的。诀窍是您不必等待 块完成。相反,块完成,然后执行所需的操作。您 viewcontroller 中的代码将无法运行,无法运行,我们也不希望它运行。相反,回调块将图像存放在某处,然后告诉 tableview 重新加载该行。

是的,下面的代码在块中,所以这将在后台继续

[[HTTPUtil sharedInstance] getImageArrayFromURL:url success:^(NSArray* array){
    imgarr = [NSArray arrayWithArray:array];
}failure:^(NSError* error){
    NSLog(@"%@", error);
}];

解决方案 - 你应该在成功块中添加 _vCycleScrollView.imageURLStringsGroup = imgarr; 因为你不知道它什么时候会完成 或者还有另一种你不应该调用的方法在块中或不应创建块。

试试下面的方法:

 __block NSArray* imgarr;
[[HTTPUtil sharedInstance] getImageArrayFromURL:url success:^(NSArray* array){
    imgarr = [NSArray arrayWithArray:array];
    NSLog(@"adding...");
    _vCycleScrollView.imageURLStringsGroup = imgarr;
}failure:^(NSError* error){
    NSLog(@"%@", error);
}];

获取数据后执行完成块。 在您的情况下,代码在设置完成块后继续执行,但尚未获取数据,这就是 imgarr 为 nil 的原因。