Синхронный вызов службы веб-API для универсального метода

Я использую RestKit версии 0.20.3, чтобы создать общий метод, который используется во многих других местах. Проблема в том, что возвращаемое значение этого метода всегда равно нулю, потому что "местоположение возврата"; оператор выполняется ПЕРЕД функцией обратного вызова Success над методом [objectManager getObjectsAtPath ...] (см. коды ниже).

Я хочу "возвратное место"; оператор должен ЖДАТЬ, пока переменная блока «местоположение» будет заполнена данными из функции обратного вызова Success внутри метода [objectManager getObjectsAtPath ...]. Как я могу это сделать?

Спасибо за помощь.

Мой общий метод выглядит так:

-(KNSunGoogleLatitudeLongitudeGeometryLocation*)getSynchronouslyLatitudeLongitudeWithAddress:(NSString*)address
{
    __block KNSunGoogleLatitudeLongitudeGeometryLocation* location = [[KNSunGoogleLatitudeLongitudeGeometryLocation alloc] init];


    NSURL *baseURL = [NSURL URLWithString:@"http://maps.googleapis.com/maps/api"];
    AFHTTPClient * client = [AFHTTPClient clientWithBaseURL:baseURL];
    [client setDefaultHeader:@"Accept" value:RKMIMETypeJSON];
    RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];


    //1. KNSunGoogleLatitudeLongitudeGeometryLocation

    RKObjectMapping *locationMapping = [RKObjectMapping mappingForClass:[KNSunGoogleLatitudeLongitudeGeometryLocation class]];
    [locationMapping addAttributeMappingsFromArray:@[@"lat", @"lng"]];


    //2. KNSunGoogleLatitudeLongitudeGeometry

    RKObjectMapping *geometryMapping = [RKObjectMapping mappingForClass:[KNSunGoogleLatitudeLongitudeGeometry class]];

    //3. KNSunGoogleLatitudeLongitude

    RKObjectMapping *latLongMapping = [RKObjectMapping mappingForClass:[KNSunGoogleLatitudeLongitude class]];



    //4. property/relationship mapping

    [geometryMapping addPropertyMapping:[RKRelationshipMapping
                                         relationshipMappingFromKeyPath:@"location"
                                         toKeyPath:@"location"
                                         withMapping:locationMapping]];

    [latLongMapping addPropertyMapping:[RKRelationshipMapping
                                        relationshipMappingFromKeyPath:@"geometry"
                                        toKeyPath:@"geometry"
                                        withMapping:geometryMapping]];



    // 6. response
    RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:latLongMapping
                                                                                             method:RKRequestMethodGET
                                                                                        pathPattern:nil
                                                                                            keyPath:@"results"
                                                                                        statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
    // 7
    [objectManager addResponseDescriptor:responseDescriptor];



    NSDictionary *queryParams;
    queryParams = [NSDictionary dictionaryWithObjectsAndKeys:address, @"address", @"false", @"sensor", nil];


    // 6

    [objectManager getObjectsAtPath:@"http://maps.googleapis.com/maps/api/geocode/json"
                         parameters:queryParams
                            success:^(RKObjectRequestOperation * operaton, RKMappingResult *mappingResult)
     {

             //-----------
             NSArray* results = [mappingResult array];
             KNSunGoogleLatitudeLongitude* result0 = [results objectAtIndex:0];
             KNSunGoogleLatitudeLongitudeGeometry* geometry = result0.geometry;

             location= geometry.location;

             NSLog(@"lat=%@, long=%@", location.lat, location.lng);


     }
                            failure:^(RKObjectRequestOperation * operaton, NSError * error)
     {
         NSLog (@"failure: operation: %@ \n\nerror: %@", operaton, error);
     }];


    return location;  // note: ALWAYS RETURNs nil 
}

person Thomas.Benz    schedule 26.09.2013    source источник


Ответы (1)


Вам нужно изменить то, что вы хотите, потому что это плохой дизайн. Вы не должны блокировать запросчика во время выполнения запроса. Вместо этого вы должны передать блок вашему общему методу, который выполняется из блока, который вы передаете в RestKit. Это позволяет правильно соблюдать асинхронный характер запроса.

Если вы хотите продолжить блокировку, вы можете посмотреть на использование семафора. Но вам нужно будет управлять этим самостоятельно. И вы никогда не сможете инициировать запрос в основном потоке. Это серьезные препятствия для общего использования, которые, вероятно, вызовут у вас проблемы в будущем.

person Wain    schedule 27.09.2013
comment
Спасибо. Я добавляю еще один параметр блока к моему существующему общему методу. Таким образом, любые коды, вызывающие общий метод, должны передавать блок для выполнения в функции успеха обратного вызова RestKit в общем методе. - person Thomas.Benz; 04.10.2013