Manzoor
Manzoor

Reputation: 57

Multi threading objective-c

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;

Upvotes: 1

Views: 91

Answers (1)

Rob
Rob

Reputation: 438162

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

Upvotes: 1

Related Questions