我只是学习使用NSURLSession API,我发现在创建这样的会话时我们只是设置了NSURLSessionDelegate。
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
并且我们没有设置NSURLSessionTaskDelegate,但是NSURLSessionTaskDelegate方法也会被调用,看来系统会在符合NSURLSessionDelegate的对象上调用NSURLSessionTaskDelegate方法吗?
更新演示代码
#import "ViewController.h"
@interface ViewController ()<NSURLSessionDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession* session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
NSURLSessionDataTask* task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];
[task resume];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
}
最佳答案
如果我理解正确,您的意思是创建了一个同时在<NSURLSessionDelegate>
和<NSURLSessionTaskDelegate>
协议中实现方法的类,但是您仅声明它实现了<NSURLSessionDelegate>
协议。然后,您在创建会话时将其作为委托传递,而对于为什么还要调用会话任务委托方法感到困惑。
首先,每个会话只有一个代表。它处理与会话有关的事件和与任务有关的事件。委托方法被分组为多个协议,以使其更易于记录和理解。任务和会话委托方法之间的区别没有运行时意义。NSURLSession
类由Apple预编译。它不是使用头文件编译的,因此不知道您传入的类对象的头文件是否具有<NSURLSessionTaskDelegate>
装饰。这些修饰仅在告诉编译器该类应包含这些方法的情况下才有意义。如果将该类的实例传递给方法,该方法的参数类型表明传入的对象必须符合<NSURLSessionTaskDelegate>
协议,而您的类不符合,则编译将失败。同样,如果协议中缺少必需的方法,则编译类将失败。但是,除了这两个目的之外,这些修饰基本上只是为了程序员的利益。
此外,由于所有NSURLSession
委托方法都是可选的,因此会话不能基于其声称要遵循的协议来假定其委托将支持任何特定方法。
由于这些原因,在运行时级别,会话通过询问委托对象是否支持该方法来确定是否调用每个委托方法。如果显示“是”,则会话将调用该方法。
因为您的类为任务和会话委托方法提供了实现,所以当类被询问是否支持这些方法时,它会自动说“是”,因此NSURLSession
在适当的时候调用它们。
关于ios - 何时设置NSURLSessionTaskDelegate?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40970666/