通用方法的同步调用 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 服务的主要内容,如果未能解决你的问题,请参考以下文章
.NET 3.5 ASMX Web 服务 - 通过 .NET 3.5 服务参考调用 - 通用类重用