Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.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中使用单例模式重构网络方法_Ios_Objective C_Uitableview_Objective C Blocks - Fatal编程技术网

尝试在iOS中使用单例模式重构网络方法

尝试在iOS中使用单例模式重构网络方法,ios,objective-c,uitableview,objective-c-blocks,Ios,Objective C,Uitableview,Objective C Blocks,我的应用程序中有以下方法,使用NSURLSession从JSON格式的web服务中提取电影数据: - (void) downloadMovieData { //this is just a visual cue to show that processing is being done [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; //creating the r

我的应用程序中有以下方法,使用
NSURLSession
从JSON格式的web服务中提取电影数据:

- (void) downloadMovieData {

    //this is just a visual cue to show that processing is being done
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

    //creating the request
    NSURL *url = [NSURL URLWithString:kMovieURL];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    //creating the session
    self.config = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:self.config];

    //the object that makes the call to the web service using the request and the session, and returns a response or an error
    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        //At this point a response has been received, so we can turn the indicator off
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

        //I am casting the response to an NSHTTPURLResponse so I can check the status code of the response
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

        //a status code of 200 means a successful connection with the web service
        if (httpResponse.statusCode == 200) {

            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"Success!");
                //I send the data that was received from the response to the method so that the JSON data is extracted
                [self populateArray:data];
            });

        } else {
            NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"Received HTTP %ld: %@", (long)httpResponse.statusCode, result);
        }
    }];

    [task resume];

}

- (void) populateArray: (NSData *)data {

    NSError *jsonError;
    NSDictionary *response =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];

    if (response) {
        self.movieObjects = response[@"movies"];
        NSLog(@"The movie objects are: %@", self.movieObjects);
        [self.tableView reloadData];
    } else {
        NSLog(@"ERROR: %@", jsonError);
    }
}
上面的代码运行良好。没有问题。但是,我现在想做的是重构我的代码,这样我就可以将所有网络代码放在包含
UITableView
委托方法的类中,而不是将代码移动到一个单独的类中,该类使用单例方法来更好地分离代码。我有如下的框架代码,如下所示:

#import "Networker.h"

@implementation Networker

+ (NSURLSession *)dataSession {
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    });
    return session;
}

+ (void)fetchContentsOfURL:(NSURL *)url completion:(void (^)(NSData *data, NSError *error)) completionHandler {

    NSURLSessionDataTask *dataTask = [[self dataSession] dataTaskWithURL:url
                      completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {

         if (completionHandler == nil) return;

         if (error) {
             completionHandler(nil, error);
             return;
         }
         completionHandler(data, nil);
     }];

    [dataTask resume];
}
我完全理解Singleton类。这不是问题所在。我的问题是理解如何理解此方法的“完成处理程序”部分:

+ (void)fetchContentsOfURL:(NSURL *)url completion:(void (^)(NSData *data, NSError *error)) completionHandler {}

我想做的是,将方法“downloadMovieData”中的代码移动到“fetchContentsOfURL”中,并返回一个
NSData
对象,然后我可以使用该对象在调用类中填充UITableView。然而,在这样做的过程中,我想确保我了解这个新方法的“completionHandler”部分发生了什么。我该怎么做呢?

您不能移动它,使它返回,因为它是异步的。从技术上讲,您可以,但是您会在等待时阻塞主线程,这很糟糕

相反,您只需将当前代码替换为对singleton的调用,并在完成块中调用其他方法来处理数据

有几件事需要注意:

  • 在单例中调用完成块之前,最好先将其分派到main,这样就不需要函数的所有用户都记得这样做
  • 它不需要是一个单例,您可以在每次需要时实例化一个类的副本,或者使用依赖项注入,这两者通常都提供了更好的体系结构

  • 非常感谢您的回复。您能解释一下在这种情况下(即iOS)您所说的“依赖注入”是什么意思吗?依赖注入,在任何语言中,都是通过将这些值传递给类(注入它们)来向类提供其需求的过程,否则该类将有代码从其他地方获取满足需求的东西。