1

I have to search database using keyword typed from key board from iphone. When ever i search the key board halts. and if i run in the background then i find an empty array. I want both key board so that key board doesnot halts and wait until array is full with data.I am using objective-c.


dispatch_semaphore_t task = dispatch_semaphore_create(0);

manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {

    } else {
        //int i=0;
        //NSLog(@"%@",responseObject);

         header=responseObject;


        dispatch_semaphore_signal(task);

    }

}];

[dataTask resume];


dispatch_semaphore_wait(task, DISPATCH_TIME_FOREVER);
return header;
1
  • it seems you are blocking your main thread by the semaphore, aren't you? Commented Jul 18, 2016 at 7:19

1 Answer 1

1

You've taken an inherently asynchronous method, dataTaskWithRequest, and have made it synchronous (i.e. it blocks the thread from which it was called). Get rid of all of that semaphore stuff. It's a really bad pattern, anyway.

I assume you did that because you wanted to return data from a network call. You shouldn't do that. You should use a completion handler pattern, e.g.


For example, let's imagine your method currently looks like:

- (id)performRequest:(NSURLRequest *)request {
    __block id header;

    manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        if (error) {

        } else {
            header = responseObject;
        }
        dispatch_semaphore_signal(semaphore);
    }];

    [dataTask resume];

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    return header;
}

You should change it to a void return type, and add a completionHandler parameter:

- (void)performRequest:(NSURLRequest *)request completionHandler:(void (^)(id _Nullable responseObject, NSError * _Nullable error))completionHandler {
    manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

    NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        if (error) {
            completionHandler(nil, error);
        } else {
            completionHandler(responseObject, nil);
        }
    }];

    [dataTask resume];
}

And you'd call it like so:

[self performRequest:request completionHandler:^(id responseObject, NSError *error) {
    // use responseObject and error here
}];

// but not here
Sign up to request clarification or add additional context in comments.

2 Comments

thanks for your reply, sir could you please write a few lines of code. so that i can get most out of it.
I've added some code, but if that's not clear, you should edit your question showing us the full method that the code is from, as well as a snippet showing us how you're calling that method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.