Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Objective-C中,是否有比委托更干净的方法来处理异步http请求?_Ios_Objective C_Api_Nsurl_Delegation - Fatal编程技术网

Ios 在Objective-C中,是否有比委托更干净的方法来处理异步http请求?

Ios 在Objective-C中,是否有比委托更干净的方法来处理异步http请求?,ios,objective-c,api,nsurl,delegation,Ios,Objective C,Api,Nsurl,Delegation,我正在构建一个iPhone应用程序,它充分利用了我用php编写的web服务。现在我有一个文件(API.h/API.m),其中包含通过NSURLConnection调用web服务上php函数的方法 方法如下: -(void) mediaAdd:(UIImage *)image withDelegate: (id<apiRequest>) delegate; -(void) mediaGet:(NSString *)imageURL withDelegate: (id<apiReq

我正在构建一个iPhone应用程序,它充分利用了我用php编写的web服务。现在我有一个文件(API.h/API.m),其中包含通过NSURLConnection调用web服务上php函数的方法

方法如下:

-(void) mediaAdd:(UIImage *)image withDelegate: (id<apiRequest>) delegate;
-(void) mediaGet:(NSString *)imageURL withDelegate: (id<apiRequest>) delegate;
…这当然是在调用API.h/API.m中的方法的控制器上执行的

我的问题是,当控制器需要进行多个API调用时,就会出现组织混乱。因为我只有单委托方法,所以我在serverResponse方法中使用call参数来区分不同的调用

下面是serverResponse方法实例的框架:

//API Delegate
-(void)serverResponse:(NSDictionary *)response fromCall:(NSString *)call {
    bool local = false;
    NSString *callbackString;
    if (local) {
        callbackString = @"http://localhost/";
    } else {
        callbackString = @"http://secret.com/";
    }
    if ([call isEqualToString:[NSString stringWithFormat:@"%@user/add",callbackString]]) {
        //user/add was called
        if (![[response objectForKey:@"status"] isEqualToString:@"fail"]) {
            if ([[response objectForKey:@"status"] isEqualToString:@"fail"]) {
                if ([[response objectForKey:@"reason"] isEqualToString:@"udid already taken"]) {
                     //UDID taken
                }
            } else {

                //UDID not taken, we're good to go



            }

        } else {
            NSLog(@"fail");
        }
    } else if([call isEqualToString:[NSString stringWithFormat:@"%@moment/get",callbackString]]){
        //moment/get was the api call
    } else if([call isEqualToString:[NSString stringWithFormat:@"%@printPictures/printPic",callbackString]]){

        //printPictures/printPic was the api call
    } else {
        NSLog(@"wrong call");
    }



}
我的问题是,我应该为每个API调用创建一个委托方法吗?或者我想得太多了,实际上有一个非常简单的方法来处理这个问题。也许是设计模式或结构

谢谢大家!!
-Mike

我通过使用一个单独的带有回调块的下载类来完成这类工作。控制器创建类的一个实例,并在回调中接收结果,然后释放下载类。您需要进行的每个调用都会创建自己的Downloader类实例,因此您不需要跟踪哪个响应与哪个调用一起进行

    Downloader *dl = [Downloader new];
    NSURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"...."]] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];

    [dl downloadWithRequest:(NSURLRequest *) request completion:^(NSData *data, NSError *error) {
        if (!error ) {
            // do whatever you need to do with the raw data here
            NSLog(@"got the data");
        }else{
            NSLog(@"%@",error);
        }
    }];
下面是我如何实现Downloader类的

typedef void(^compBlock)(NSData *data, NSError *error);

@interface Downloader : NSObject <NSURLConnectionDataDelegate>

-(void)downloadWithRequest:(NSURLRequest *) request completion:(compBlock) completion;

@end
我的问题是,当控制器需要进行多个API调用时,就会出现组织混乱

对于这种情况,您应该真正了解
NSURLSession
和相关类
NSURLSession
提供了类似于
-sendAsynchronousRequest:queue:completionHandler:
的方法,使您无需提供自己的委托对象即可完成任务--会话将为您提供一个默认委托,任务完成时,默认委托将调用您的完成处理程序

当然,您仍然可以选择提供自己的代理,并且每个任务都有一个标识符,这样您的代理就可以比使用
NSURLConnection
更容易地跟踪哪个任务是哪个任务


我不会在这里详细介绍
NSURLSession
的所有好处,因为你可以自己做,但它们很重要。如果您正在编写新代码,几乎可以肯定应该使用
NSURLSession
而不是
NSURLConnection

非主题观察,但现在看一下框架,我有很多多余的代码。。哈哈。注意我注意到了这一点,所以我知道这是个问题。你可以传递一个完成块而不是一个委托。当然,你意识到你可以为一个给定的委托协议创建多个委托对象吗?要解决您的问题,只需为每个API调用创建一个对象。热舔,我在问题中提到了该解决方案,但除非它是最后一个可用选项,否则我不想继续讨论。请注意,“分离委托对象”与“分离委托方法”不同。您可以拥有同一委托类的多个副本,实现同一委托方法。此方法不需要同步请求吗?或者可能是不同队列上的同步请求?@MichaelKing,不是,在Downloader类中,我将NSURLConnection与常用的委托方法一起使用。回调块是在didFailWithError或ConnectionDiFinishLoading中调用的。我没有意识到回调块可以位于单独的位置。我想我需要更多地了解积木,以及它们是如何工作的。你手头有什么好的资源吗?@MichaelKing,没有,除了苹果的文档之外,我不知道还有什么特别好的资源。如果你想知道我是如何实现它的,我可以发布downloader类的代码。那太好了!非常感谢。
typedef void(^compBlock)(NSData *data, NSError *error);

@interface Downloader : NSObject <NSURLConnectionDataDelegate>

-(void)downloadWithRequest:(NSURLRequest *) request completion:(compBlock) completion;

@end
@interface Downloader()
@property (copy,nonatomic) compBlock completionHandler;
@property (strong,nonatomic) NSMutableData *receivedData;
@end

@implementation Downloader

-(void)downloadWithRequest:(NSURLRequest *) request completion:(compBlock)completion {
    NSURLConnection *con = [NSURLConnection connectionWithRequest:request delegate:self];
    if (con) {
        self.receivedData = [NSMutableData new];
        self.completionHandler = completion;
    }
}


-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    self.receivedData.length = 0;
}



-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.receivedData appendData:data];
}



-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    self.completionHandler(nil, error);
}



-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
    self.completionHandler(self.receivedData, nil);
}