【问题标题】:Checking which kind of NSURLSessionTask occurred检查发生了哪种 NSURLSessionTask
【发布时间】:2014-08-21 10:33:07
【问题描述】:

我好像遇到了麻烦。出于某种原因,如果我尝试检查 NSURLSessionTask 对象的类类型,它根本不起作用。如果我检查他们的taskDescription 属性,那么如果我在启动任务之前设置它们当然可以。我只想知道为什么下面的代码对我不起作用。感谢您提供的任何帮助!

- (void)uploadIt
{
    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
    defaultConfigObject.timeoutIntervalForResource = 15.0;
    defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;

    NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    NSURLSessionUploadTask *uploadTask = [defaultSession uploadTaskWithRequest:someRequest fromData:body];
    [uploadTask resume];
}  

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    if (self.uploadResponseData)
    {
        NSDictionary *d = [NSJSONSerialization JSONObjectWithData:self.uploadResponseData options:kNilOptions error:nil];
        NSLog(@"Dict: %@",d);
    }

    if ([task isKindOfClass:[NSURLSessionDownloadTask class]])
    {
        // Not called
    }
    else if ([task isKindOfClass:[NSURLSessionUploadTask class]])
    {
        // Not called
    }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    if (!self.uploadResponseData)
    {
        self.uploadResponseData = [NSMutableData dataWithData:data];
    }
    else
    {
        [self.uploadResponseData appendData:data];
    }
}

【问题讨论】:

  • 对于初学者来说,你的任务什么样的课程?在上面的代码中,如果它是 NSURLDataTask,那么不调用“未调用”部分将是完全有效的。
  • NSURLSessionDownload 和上传任务是NSURLSessionDataTask 的子类,但是NSURLSessionDataTaskNSURLSessionTask 的子类,所以我不明白为什么这不起作用。
  • 我错过了什么吗?我在问你期望的任务是什么类型的,因为如果它是一个 NSURLDataTask,这意味着它既不是 NSURLSessionUploadTask,也不是 NSURLSessionDownloadTask,这可以解释为什么你的代码不起作用。我想这也是你刚才所说的。 NSURLSessionDataTask 作为 NSURLSessionTask 的子类与我的观点没有任何关系,据我所知......
  • 那么如何调用isKindOfClass isKindOfClass 两次得到超类呢?
  • 我可以再问一次:您要检测的任务是什么类?

标签: ios objective-c nsurlsession nsurlsessiontask nsurlsessionuploadtask


【解决方案1】:

我在这方面的经验是在后台应用程序NSURLSessionTasks 的背景下进行的。这些被序列化到磁盘上,其中涉及到一个守护进程,我的经验是,任何基于类的 finagling 在这种情况下都不能很好地工作。

特别是,我试图继承 NSURLSessionTask,但在 -didComplete:... 调用中返回的不是该子类的实例。

我开始认为NSURLSessionTask 是一个门面,或者是“类集群”的一部分,并试图更加小心。

如果您需要将任务标记为特定类型,您可以在.description 中存储您喜欢的任何内容。我可以确认信息很好地在后台序列化中幸存下来。

【讨论】:

    【解决方案2】:

    我无法从您发布的代码中重现该问题。我从您的代码中做了一个最小的示例,只是从标准 Xcode 模板创建了一个单视图应用程序,然后将其用作视图控制器:

    ViewController.h:

    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController <NSURLSessionDelegate, NSURLSessionTaskDelegate>
    
    @end
    

    ViewController.m:

    #import "ViewController.h"
    
    @interface ViewController ()
    
    
    @end
    
    @implementation ViewController
    
     1. (void)viewDidLoad {
        [super viewDidLoad];
        [self uploadIt];
    }
    
     2. (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
     3. (void)uploadIt
    {
        NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
        defaultConfigObject.timeoutIntervalForResource = 15.0;
        defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
    
        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    
        NSURLRequest* someRequest = [NSURLRequest requestWithURL: [NSURL URLWithString:@"http://example.com"]];
        NSData* body = [@"Fake body" dataUsingEncoding:NSUTF8StringEncoding];
    
        NSURLSessionUploadTask *uploadTask = [defaultSession uploadTaskWithRequest:someRequest fromData:body];
        [uploadTask resume];
    }
    
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
        NSLog(@"Completed.");
    
        if ([task isKindOfClass:[NSURLSessionDownloadTask class]])
        {
            NSLog(@"The task was a download task");
        }
        else if ([task isKindOfClass:[NSURLSessionUploadTask class]])
        {
            NSLog(@"The task was an upload task");
        }
    }
    @end
    

    结果如下:

    2014-07-02 17:57:28.002 24500545_nsurlsession_classes[22470:1250475] 已完成。 2014-07-02 17:57:48.631 24500545_nsurlsession_classes[22470:1250475] 任务是上传任务

    (您确定您的日志记录正确吗?如果您在委托方法中设置断点并单步执行代码,您会看到什么?p task 在 lldb 中告诉您什么?)

    【讨论】:

    • 嗯,如果我做一个准系统项目,它当然可以工作。好奇怪!
    • 其实我还是有问题。如果我启动一个 NSURLSessionUploadTask,那么([task isKindOfClass:[NSURLSessionDownloadTask class]]) 的 if 语句仍然会被调用。奇怪
    • 您的代码与原始帖子中的代码相同,还是发生了变化? (如果相同,并且“if”语句中没有任何内容,您如何检查它是否已执行?想知道您是否由于优化而看到某种奇怪的结果,或者其他什么......)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 2022-10-14
    • 2023-02-10
    • 2017-01-12
    • 1970-01-01
    • 2014-10-05
    相关资源
    最近更新 更多