Viet Nguyen
Viet Nguyen

Reputation: 2373

iOS wait block until complete

I have created a block void function which is using AFNetworking library. This function is used for GET request and uses like so.

[Mics getRequestBLOCK:clientsUrlStr BlockRequest:^(NSString *response) {
    //use response here
}];

Everything work fine, but I really get a headache when I use this block in a function that need return a value, for instance.

+ (NSArray*)OnlineClients
{
    NSString *clientsUrlStr = [NSString stringWithFormat:@"%@/sinch/clients", ROOT_URL];
    __block NSArray *clients = [[NSArray alloc] init];
    [Mics getRequestBLOCK:clientsUrlStr BlockRequest:^(NSString *response) {
        clients = [response componentsSeparatedByString: @","];
    }];

    return clients;
}

OnlineClients array function always return 0 item because request block is not finished with completion.

So, how can I wait for block completion to get response request for return in a function?

I have been searching various topics in StackOverflow and Google but can't found any solution.

Please help.

Upvotes: 0

Views: 2208

Answers (2)

oskarko
oskarko

Reputation: 4168

An UGLY solution but it's works!

__block BOOL isChecked = NO;
YourService *yourService = [[YourService alloc] init];
[yourService checkStatus:string completionHandler:^(BOOL isSuccessful, Error *err) {
    isValid = err ? NO : isSuccessful;
    isChecked = YES;
}];
while (!isChecked) {
    [NSThread 0.6];
}

Upvotes: 0

HSG
HSG

Reputation: 1224

There are several possibilities to deal with your problem. You are able to either use dispatch_group or dispatch_semaphore to wait for the response from async call before return value or modify your method to have a block to callback the response. Please take a look on codes below. To be NOTICED that dispatch_group and dispatch_semaphore are going to block the current thread to wait until another one triggers a signal, therefore, should not use it on the main thread. In my opinion, I would suggest the 3rd solution. I hope it would help you.

//1
+ (NSArray*)OnlineClients
{
    dispatch_group_t serviceGroup = dispatch_group_create();

    NSString *clientsUrlStr = [NSString stringWithFormat:@"%@/sinch/clients", ROOT_URL];
    __block NSArray *clients = [[NSArray alloc] init];
    [Mics getRequestBLOCK:clientsUrlStr BlockRequest:^(NSString *response) {
        clients = [response componentsSeparatedByString: @","];
        dispatch_group_leave(serviceGroup);
    }];

    dispatch_group_enter(serviceGroup);

    return clients;
}

//2
+ (NSArray*)OnlineClients
{
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);

    NSString *clientsUrlStr = [NSString stringWithFormat:@"%@/sinch/clients", ROOT_URL];
    __block NSArray *clients = [[NSArray alloc] init];
    [Mics getRequestBLOCK:clientsUrlStr BlockRequest:^(NSString *response) {
        clients = [response componentsSeparatedByString: @","];
        dispatch_semaphore_signal(sema);
    }];

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    return clients;
}

//3
+ (void)getOnlineClientsWithCompletionBlock:(void (^) (NSArray *clients))completionBlock
{   
    NSString *clientsUrlStr = [NSString stringWithFormat:@"%@/sinch/clients", ROOT_URL];
    __block NSArray *clients = [[NSArray alloc] init];
    [Mics getRequestBLOCK:clientsUrlStr BlockRequest:^(NSString *response) {
        clients = [response componentsSeparatedByString: @","];
        if (completionBlock) {
            completionBlock(clients);
        }
    }];

}

Upvotes: 3

Related Questions