Reputation: 3363
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?
Upvotes: 0
Views: 64
Reputation: 917
Try bellow:
__block NSArray* imgarr;
[[HTTPUtil sharedInstance] getImageArrayFromURL:url success:^(NSArray* array){
imgarr = [NSArray arrayWithArray:array];
NSLog(@"adding...");
_vCycleScrollView.imageURLStringsGroup = imgarr;
}failure:^(NSError* error){
NSLog(@"%@", error);
}];
The completion block is executed once data is fetched. In your case code continues to execute after the completion block is set but data hasn't been fetched yet, that's why imgarr is nil.
Upvotes: 1
Reputation: 114
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.
Upvotes: 2
Reputation: 52632
That's the whole idea: That blocks are executed out of order. The trick is that you don't wait for a block to finish. Instead, the block finishes and then it does what is needed. The code in your viewcontroller isn't going to work, can't work, and we don't want it to work. Instead, the callback block deposits the image somewhere, and then tells the tableview to reload the row.
Upvotes: 0