Tom Lilletveit
Tom Lilletveit

Reputation: 2002

Obj-C: Usage of callbacks

There is a method in the Google Maps SDK that uses callbacks like these, I guess it´s blocks? anyways I have never used these before. I just want to see if the method requestPanoramaNearCoordinate returns a valid Panorama near the coordinate i give it. How do i use the callback to see what the callback returns? If it returns a valid Panorama at the coordinate I want to return it - if not I´ll recursively call the method until a valid location is found

- (void) requestPanoramaNearCoordinate: (CLLocationCoordinate2D)coordinate
                              callback: (GMSPanoramaCallback)callback 

Retrieves information about a panorama near the given coordinate. This is an asynchronous request, callback will be called with the result.

CLLocationCoordinate2D ranLatLng = CLLocationCoordinate2DMake(ranLatitude,  ranLongitude);

if ([panoService requestPanoramaNearCoordinate:ranLatLng callback:<#^(GMSPanorama *panorama, NSError *error)callback#>)

Upvotes: 0

Views: 294

Answers (2)

danh
danh

Reputation: 62686

It's a block. You make the api call like this:

[aPanoramaService requestPanoramaNearCoordinate:aCoordiante callback:^(GMSPanorama *panorama, NSError *error) {
    NSLog(@"the service returned a panorama=%@ and an error=%@", panorama, error);
}];

One way to do the recursion is to build a method with a similar signature to the google method. An important point is to find a way for the recursion to stop, possibly because you get tired of searching.

- (void)findPanoramaAtLocation:(CLLocationCoordinate2D)location withCompletion:(void (^)(GMSPanorama *, NSError *))completion {

    [self.panoramaService requestPanoramaNearCoordinate:location callback:^(GMSPanorama *panorama, NSError *error) {
        if (error) {
            completion(nil, error);
        } else if (panorama) {
            completion(panorama, nil);
        } else {

            if (/* should we continue searching? */) {

                // compute a new location to try
                double latitude = // compute new latitude
                double longitude = // compute new longitude
                CLLocationCoordinate2D newLocation = CLLocationCoordinate2DMake(latitude, longitude);

                [self findPanoramaAtLocation:newLocation withCompletion:completion];

            } else {
                // no panorama and no error means we gave up
                completion(nil, nil);
            }
        }
    }];
}

This will run, calling the "callback" (it's a block) when either a panorama location is found, when an error occurs, or when your logic determines that it ought to stop searching.

Upvotes: 1

jscs
jscs

Reputation: 64002

The panorama parameter contains the GMSPanorama object that the request found for you. It doesn't seem to be documented very clearly, but the usual pattern in Cocoa is that if nothing appropriate was found, the result will be nil, and the NSError object will give you a little information about why. As for re-making the request, that would look something like this I guess:

// Necessary if GMSPanoService is ill-behaved and keeps the Block
// around after calling it.
__weak GMSPanoramaService weak_panoService = panoService;

__block GMSPanoramaCallback cb;
cb = [^(GMSPanorama *panorama, NSError *error){
    if( !panorama ){
        // Do something with error if desired
        CLLocationCoordinate2D newLatLng = /* Calc new coordinates somehow */; 
        [/*weak_*/panoService requestPanoramaNearCoordinate:newLatLng 
                                          callback:cb];
    }
    else {
        // Got a panorama, do something with it
        cb = nil;    // Release Block
    }
} copy];

[panoService requestPanoramaNearCoordinate:ranLatLng 
                                  callback:cb];

Upvotes: 1

Related Questions