gpt4 book ai didi

ios - 非唯一的 NSURLSessionDataTask taskIdentifiers

转载 作者:可可西里 更新时间:2023-11-01 05:54:29 26 4
gpt4 key购买 nike

我有一个 iOS 应用程序,它使用 NSOperationQueue、NSOperations 和 AFNetworking 2.1.0 来触发对服务器的请求。 -[NSOperation main] 方法看起来像这样:

- (void)main {
AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager sharedSessionManager];
[sessionManager GET:@"url"
parameters:nil
success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"Success");
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"Failure");
}
];
}

我注意到,有时,当创建多个操作并将其快速连续添加到 NSOperationQueue 时,特定操作的回调永远不会执行。我深入研究 AFNetworking 试图找出原因。我最终进入了 -[AFURLSessionManager dataTaskWithRequest:completionHandler],它看起来像:

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];

AFURLSessionManagerTaskDelegate *delegate = [AFURLSessionManagerTaskDelegate delegateForManager:self completionHandler:completionHandler];
[self setDelegate:delegate forTask:dataTask];

return dataTask;
}

我在创建 dataTask 后立即添加了一条日志语句:

NSLog(@"Task with id %@ created for %@ on queue %@", @(dataTask.taskIdentifier), request.URL.path, dispatch_get_current_queue());

日志揭示了问题:

2014-02-26 14:11:25.071 App[50094:6a2f] Task with id 15 created for /url1 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>
2014-02-26 14:11:25.071 App[50094:460f] Task with id 16 created for /url2 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>

2014-02-26 14:11:26.274 App[50094:6a2f] Task with id 18 created for /url2 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>
2014-02-26 14:11:26.274 App[50094:6c17] Task with id 17 created for /url1 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>

2014-02-26 14:11:27.546 App[50094:6307] Task with id 20 created for /url2 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>
2014-02-26 14:11:27.546 App[50094:6b17] Task with id 19 created for /url1 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>

2014-02-26 14:11:28.705 App[50094:6b17] Task with id 21 created for /url1 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>
2014-02-26 14:11:28.705 App[50094:6307] Task with id 21 created for /url2 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>

2014-02-26 14:11:32.091 App[50094:6307] Task with id 22 created for /url2 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>
2014-02-26 14:11:32.091 App[50094:6b17] Task with id 23 created for /url1 on queue <OS_dispatch_queue: NSOperationQueue 0xc4b8560[0xc4b8ac0]>

请注意日志中的第四组具有相同的 taskIdentifier,这是 AFNetworking 用于通过委托(delegate)将任务与其回调相关联的内容。

如果我强制 NSOperations 在主队列上运行,那么我将无法重现问题 - taskIdentifier 始终是唯一的。

有没有人见过这样的事情?我是否需要确保 -[NSURLSession dataTaskWithRequest:] 仅在主线程上运行以避免 taskIdentifier 冲突?

最佳答案

不知道这是否仍然与您相关,但这件事让我整晚都在苦思冥想。原来你部分回答了你问题中的问题。

事实证明,如果

NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];

是异步运行的,那么 NSURLSession 的实例很可能会将相同的 taskIdentifier 分配给不同的任务。

如果不 fork AFNetworking 并同步所有 dataTaskWithRequest: 方法,那么我可以通过两种方法解决这个问题。

如果您不需要从该方法返回的 NSURLSessionTask 那么最好的方法是创建您自己的调度队列以及您希望通过 session 管理器发出的任何请求,只需将其发送到该队列像这样异步:

static dispatch_queue_t my_queue;
my_queue = dispatch_queue_create("MyQueueName", DISPATCH_QUEUE_CONCURRENT);

// ... Later, that very same day

dispatch_async(my_queue, ^{
// [sessionManager GET: ...
});

然而,对于您的问题,此方法的唯一问题是它似乎都是在同一个操作队列上执行的,因此这种方法可能不适用于您的情况。另一种方法(我就是这样做的)实际上更简单。只需在 AFURLSessionManager 上同步,这样 dataTaskWithRequest: 的调用就只能像这样同步发生:

@synchronized(sessionManager) {
// [sessionManager GET: ...
}

或者,是的,您可以只在主线程上创建任务。但对于某些项目而言,它并不总是那么简单。

关于ios - 非唯一的 NSURLSessionDataTask taskIdentifiers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22054823/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com