penguin-penpen penguin-penpen - 6 months ago 15
iOS Question

ios - Program with block executed out of order?

I'm trying to get an array of urls from my backend.

I use

AFNetworking
and I have a
HTTPUtil
class implemented as
singleton
to handle my requests.

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);
}];
}


In my view controller, I call the method to fetch the array.

_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);
}];


In the console, I got

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


I thought
imgArr
should be assigned in the
success
block and it shouldn't be
nil
when I assign it to
_vCycleScrollView.imageURLStringsGroup
.


However, I can tell from the output in the console that the
HTTP
request is sent after
NSLog(@"adding...");
and that leads to the fact that
imgArr
is still
nil
when
_vCycleScrollView.imageURLStringsGroup = imgarr;
is executed.

Why is that?

Answer

Yes below code is in block so this will continue in background

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

solution - You should add _vCycleScrollView.imageURLStringsGroup = imgarr; inside of success block because you d0 not know when it will completed Or there is another way you should not call in block or should not create block.