Frage

I am trying to use dispatch queue so I can wait for one portion of code to finish before continuing onto the second portion. Below is my code, I would like for the code within the dispatch_sync to execute and complete before the code in dispatch_barrier_async. I have looked around trying to figure out why this doesn't work to no avail. Any help is appreciated.

__block dispatch_queue_t queue;
queue = dispatch_queue_create("com.example.myQueueForMaps", DISPATCH_QUEUE_CONCURRENT);

dispatch_sync(queue, ^{

    for(XYZToDoItem* item in toDoItems){

        MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
        request.naturalLanguageQuery = item.itemName;
        // somehow deal with radius
        MKCoordinateSpan span = MKCoordinateSpanMake(0.1, 0.1);
        request.region = MKCoordinateRegionMake(currentLoc.coordinate, span);

        MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];
        [search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){
            int i = 0;
            double minimum = INFINITY;
            MKMapItem *closest;

            for (MKMapItem *item in response.mapItems) {

                UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 50 + 20*i, 300, 200)];
                myLabel.numberOfLines = 1;

                NSString *myString = [NSString stringWithFormat:@"%@ %@", item.name, item.phoneNumber];
                myLabel.text = myString;

                CLLocation *loc = item.placemark.location;
                CLLocationDistance dist = [currentLoc distanceFromLocation:loc];

                if (dist < minimum) {
                    minimum = dist;
                    closest = item;
                }
                //NSLog(@"%@", closest.name);
                //NSLog(@"dist %f", minimum);
            }

            if (minimum < item.radius) {
                NSLog(@"match %@", closest.name);
                item.closeMatch = closest;
                item.match = true;
            }
            else {
                item.match = false;
                item.closeMatch = nil;
            }
        }];
    }
});

dispatch_barrier_async(queue, ^{
    [findMatches notifyNearbyTasks];
});
War es hilfreich?

Lösung

The code in your dispatch_sync() block should indeed finish executing before your barrier block. The same isn't true for the code in the completion block that you pass to -[MKLocalSearch startWithCompletionHandler:], however. -startWithCompletionHandler: is an asynchronous method, and there's a good chance that the search won't complete before the end of the block in which you start it.

Note that the completion block runs on the main thread -- from the docs:

The provided completion handler is always executed on your app’s main thread.

That is, the completion block won't be scheduled on your queue, but on the main dispatch queue instead. So, even if the completion block were scheduled before your synchronous block completes, it would be scheduled on a different dispatch queue and wouldn't prevent the barrier block from starting.

It looks like your goal is to delay the call to [findMatches notifyNearbyTasks] until all the searches have completed. One way to do that might be to add each search to a list, and have the completion block check remove the search from the list, check the size of the list, and make the appropriate call when the list is empty.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top