这可能是一个愚蠢的问题。对不起,如果是。
但是我正在开发一个使用Web服务的项目。我可以连接到Web服务并获得我需要的数据。
我想要一个方法,将从Web服务获得的数据返回给调用方。唯一的问题是,只能在ConnectionDidFinishLoading方法内部获取数据,而无法从我的方法访问此数据。
这是我的代码,可以正常工作:
- (NSData *) dataForMethod:(NSString *)webMethod withPostString:(NSString *)postString
{
NSURL *url = [NSURL URLWithString:[SigameWebServiceAddress stringByAppendingFormat:@"%@%@", @"/", webMethod]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:@"%d", [postString length]];
[req addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[req addValue:msgLength forHTTPHeaderField:@"Content-Length"];
[req setHTTPMethod:@"POST"];
[req setHTTPBody: [postString dataUsingEncoding:NSUTF8StringEncoding]];
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn)
{
webData = [NSMutableData data];
}
// I WOULD LIKE TO RETURN WEBDATA TO THE CALLER HERE, BUT WEBDATA IS EMPTY NOW, THE
//connectionDidFinishLoading ONLY GETS CALLED WITH THE DATA I WANT AFTER THE COMPILER
//IS DONE EXECUTING MY METHOD.
}
-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response
{
[webData setLength: 0];
}
-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data
{
[webData appendData:data];
}
-(void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error
{
NSLog(@"FATAL ERROR");
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
NSLog(@"DONE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
//---shows the XML---
NSLog(@"%@", theXML); //NOW, THIS IS THE DATA I WANT. BUT HOW CAN I RETURN THIS TO
//THE CALLER. I MEAN, THE CALLER THAT CALLED MY METHOD
//+ (NSData *) dataForMethod: withPostString:
}
感谢您的任何帮助!
谢谢
最佳答案
确实有两种方法可以解决此问题。
我强烈建议您不要使用同步方法-除非您已经/已经围绕它们创建了自己的异步框架(即您正在手动启动另一个线程并在该线程上执行同步请求)。从长远来看,您将意识到您需要异步的请求,并且您必须对所有请求进行重新处理。
为了快速概述我提供的两个选项:
1.创建一个委托(delegate)接口(interface)
这里的想法是创建一个执行请求的类,并创建调用者必须实现的协议(protocol)。请求完成后,您将使用数据在委托(delegate)上调用指定的方法:
该协议(protocol)可能看起来像这样:
@protocol RequestClassDelegate <NSObject>
- (void)requestCompleted:(ResponseClass *)data;
- (void)requestError:(NSError *)error;
@end
发出请求的类可能如下所示:
@interface RequestClass : NSObject
- (void)makeRequest:(id<RequestClassDelegate>)delegate;
@end
除了连接逻辑之外,请求类的实现可能还包含以下一些内容:
@implementation RequestClass
{
__weak id<RequestClassDelegate> _delegate;
}
// Connection Logic, etc.
- (void)makeRequest:(id<RequestClassDelegate>)delegate
{
_delegate = delegate;
// Initiate the request...
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
// Processing, etc.
// Here we'll call the delegate with the result:
[_delegate requestCompleted:theResult];
}
@end
2.使用块
此解决方案与第一个解决方案大致相同-但在我看来有点优雅。在这里,我们将
RequestClass
更改为使用块而不是委托(delegate):typedef void (^requestCompletedBlock)(id);
typedef void (^requestErrorBlock)(NSError *);
@interface RequestClass : NSObject
@property (nonatomic, copy) requestCompletedBlock completed;
@property (nonatomic, copy) requestErrorBlock errored;
- (void)makeRequest:(requestCompletedBlock)completed error:(requestErrorBlock)error;
@end
那样的实现可能看起来像这样:
@implementation RequestClass
@synthesize completed = _completed;
@synthesize errored = _errored;
// Connection Logic, etc.
- (void)makeRequest:(requestCompletedBlock)completed error:(requestErrorBlock)error
{
self.completed = completed;
self.errored = error;
// Initiate the request...
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
{
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
// Processing, etc.
// Here we'll call the delegate with the result:
self.completed(theResult);
}
@end
关于iphone - 如何返回从Objective-C(iPhone)的Web服务获取的数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8864699/