Ios 为什么NSURLSession dataTaskWithURL比NSData dataWithContentsOfURL慢得多?

Ios 为什么NSURLSession dataTaskWithURL比NSData dataWithContentsOfURL慢得多?,ios,performance,nsdata,nsurlsession,Ios,Performance,Nsdata,Nsurlsession,我正在尝试从我的服务器下载一个94KB的图像文件。我尝试了两种方法:使用NSURLSession datatask with url和NSData data with contents of url NSURL会议: Globals *global = [Globals getInstance]; // GET request to /mobile/image NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/m

我正在尝试从我的服务器下载一个94KB的图像文件。我尝试了两种方法:使用
NSURLSession datatask with url
NSData data with contents of url

NSURL会议:

Globals *global = [Globals getInstance];

// GET request to /mobile/image
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/mobile/image/%@", [global rootUrl], self.photoId]];
NSURLSession * session = [global session];
NSDate *start = [NSDate date];
[[session dataTaskWithURL:url completionHandler:^(NSData *imgData, NSURLResponse *response, NSError *error) {
    NSLog(@"Time taken: %f", [[NSDate date] timeIntervalSinceDate:start]);
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
    if ([httpResponse statusCode] != 200) {
        // error
    } else {
        dispatch_async(dispatch_get_main_queue(), ^ {
            UIImage *image = [UIImage imageWithData:imgData];

            CGFloat width = self.photoImageView.frame.size.width;
            CGFloat height = image.size.height / image.size.width * width;
            self.imageHeight.constant = height;

            self.photoImageView.image = image;
        });
    }
}] resume];
Time taken: 6.585221
Time taken: 3.619189
Time taken: 4.408179
Time taken: 9.931350
Time taken: 3.689192
NSData:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {
    Globals *global = [Globals getInstance];

    // GET request to /mobile/image
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/mobile/image/%@", [global rootUrl], self.photoId]];
    NSDate *start = [NSDate date];
    NSData *imgData = [NSData dataWithContentsOfURL:url];
    NSLog(@"Time taken: %f", [[NSDate date] timeIntervalSinceDate:start]);
    UIImage *image = [UIImage imageWithData:imgData];

    CGFloat width = self.photoImageView.frame.size.width;
    CGFloat height = image.size.height / image.size.width * width;

    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageHeight.constant = height;
        self.photoImageView.image = image;
    });
});
Time taken: 0.157747
Time taken: 0.135785
Time taken: 0.576947
Time taken: 0.462661
Time taken: 0.337266
以下是我的NSLog的输出,它们完成所用的时间:

NSURL会议:

Globals *global = [Globals getInstance];

// GET request to /mobile/image
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/mobile/image/%@", [global rootUrl], self.photoId]];
NSURLSession * session = [global session];
NSDate *start = [NSDate date];
[[session dataTaskWithURL:url completionHandler:^(NSData *imgData, NSURLResponse *response, NSError *error) {
    NSLog(@"Time taken: %f", [[NSDate date] timeIntervalSinceDate:start]);
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
    if ([httpResponse statusCode] != 200) {
        // error
    } else {
        dispatch_async(dispatch_get_main_queue(), ^ {
            UIImage *image = [UIImage imageWithData:imgData];

            CGFloat width = self.photoImageView.frame.size.width;
            CGFloat height = image.size.height / image.size.width * width;
            self.imageHeight.constant = height;

            self.photoImageView.image = image;
        });
    }
}] resume];
Time taken: 6.585221
Time taken: 3.619189
Time taken: 4.408179
Time taken: 9.931350
Time taken: 3.689192
NSData:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {
    Globals *global = [Globals getInstance];

    // GET request to /mobile/image
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/mobile/image/%@", [global rootUrl], self.photoId]];
    NSDate *start = [NSDate date];
    NSData *imgData = [NSData dataWithContentsOfURL:url];
    NSLog(@"Time taken: %f", [[NSDate date] timeIntervalSinceDate:start]);
    UIImage *image = [UIImage imageWithData:imgData];

    CGFloat width = self.photoImageView.frame.size.width;
    CGFloat height = image.size.height / image.size.width * width;

    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageHeight.constant = height;
        self.photoImageView.image = image;
    });
});
Time taken: 0.157747
Time taken: 0.135785
Time taken: 0.576947
Time taken: 0.462661
Time taken: 0.337266

下载一个简单的需要3~10秒,您遇到了线程问题。不要在后台线程中运行该代码(NSURLSession代码)!在主线程上运行它。别担心,这不会阻塞主线程;NSURLSession的关键在于它可以异步运行,这样您就不必这样做了。

也许有必要在会话的配置(NSURLSessionConfiguration。我从缓存开始)上瞎搞一下,看看是否有什么东西对时间有很大影响。我没有费心缓存,因为我也没有缓存NSData。(两者都完全干净地运行。)至于我的会话配置:
NSURLSessionConfiguration*config=[NSURLSessionConfiguration defaultSessionConfiguration]
nsursession*session=[nsursession sessionWithConfiguration:config]几乎是默认的,而且我在其他任何地方都没有更改过任何配置。当我查看NSURLISTIN的网络使用时,它似乎在下载任务的中间下降到零KB/s,然后在几秒钟后返回,重复到完成。这可能与它在后台运行有关吗?问题不在于上面的代码。问题也不在于
NSURLSession
,这是一段非常健壮的网络代码。提供的代码不足以重现您描述的问题。也许你可以构建一个能体现你所描述的问题的模型,并与我们分享?@pchiang你应该继续,将你的结论作为“答案”发布,而不是用你的发现编辑问题。您的论点是,如果您碰巧从后台线程使用
NSURLSession
,您会看到这样的延迟吗?与
NSURLConnection
不同,
NSURLSession
似乎在您想要运行它的任何线程上都表现得很好。@Rob不,我认为他的线程问题在别处;我们不知道的事情正在争论中。我只是想让他离开后台线程,因为它们很难处理。同意,问题在于其他地方,而不是问题中提供的代码。我找到了答案,谢谢你的帮助!我用这个项目的所有连接创建了一个全新的项目,它执行得很好。问题:在此之前的VC多次调用dataTask。我完全不明白为什么这会影响到这个VC。结果表明,该类名为ViewController(默认名称),并且该VC继承的是ViewController而不是UIViewController。因此,从这个ViewController的
viewDidLoad
调用
[super viewDidLoad]
实际上是在调用上一个VC并重新运行所有这些数据任务。这很好,但我认为我不值得为此“接受”!我们猜想问题出在别处,但仅此而已。