通用方法的同步调用 Web API 服务

Posted

技术标签:

【中文标题】通用方法的同步调用 Web API 服务【英文标题】:Synchronous calling web API service for a generic method 【发布时间】:2013-09-26 19:38:15 【问题描述】:

我正在使用 RestKit 版本 0.20.3 来制作一个在许多其他地方使用的通用方法。问题是该方法的返回值始终为零,因为“返回位置;”语句在成功回调函数之前通过 [objectManager getObjectsAtPath ...] 方法执行(参见下面的代码)。

我想要“返回位置”;语句必须等待块变量“location”填充来自 [objectManager getObjectsAtPath ...] 方法内的 Success 回调函数的数据。我怎样才能做到这一点?

感谢您的帮助。

我的通用方法如下所示:

-(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 

【问题讨论】:

【参考方案1】:

你需要改变你想要的,因为这是一个糟糕的设计。当请求正在进行时,您不应阻止请求者。相反,您应该将一个块传递给您的通用方法,该方法从您传递给 RestKit 的块中执行。这使您能够正确地尊重请求的异步性质。

如果您确实想继续进行阻塞,您可以使用信号量查看。但是,您需要自己管理。而且您永远无法在主线程上触发请求。这些是一般使用的重大障碍,可能会在未来给您带来问题。

【讨论】:

谢谢。我为现有的通用方法创建了另一个块参数。所以,任何调用通用方法的代码都需要在通用方法中RestKit的回调成功函数处传入一个block执行。

以上是关于通用方法的同步调用 Web API 服务的主要内容,如果未能解决你的问题,请参考以下文章

WEB通用抽奖程序设计 开放的API接口

.NET 3.5 ASMX Web 服务 - 通过 .NET 3.5 服务参考调用 - 通用类重用

.NET 2 ASMX Web 服务 - 通过 .NET 3.5 服务参考调用 - 通用类重用

如何制作调用不同服务的通用方法

打字稿通用服务

通用构建请求方法响应未定义