如何解决带委托的NSURLSession在主线程上不起作用
我希望在主线程上调用NSURLSession的委托。当我将[NSOperationQueue mainQueue]
传递给delegateQueue
时,没有调用该代表团。
@interface NSURLSessionTests : XCTestCase<NSURLSessionDataDelegate>
{
@private
dispatch_semaphore_t _semaphore;
}
@end
@implementation NSURLSessionTests
- (void)testWithRequest{
NSMutableuRLRequest *request = [NSMutableuRLRequest requestWithURL:[NSURL URLWithString: @"http://example.com/"]];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
_semaphore = dispatch_semaphore_create(0);
[dataTask resume];
NSLog(@"Start: %@",dataTask);
dispatch_semaphore_wait(_semaphore,disPATCH_TIME_FOREVER);
}
# pragma mark NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponsedisposition disposition))completionHandler {
NSLog(@"didReceiveResponse: %@",NSThread.currentThread);
NSLog(@"%@",response);
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
NSLog(@"didReceiveData: %@",data);
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"didCompleteWithError: %@",error);
dispatch_semaphore_signal(_semaphore);
}
@end
执行结果如下。
Test Suite 'Selected tests' started at 2020-10-19 16:53:56.013
Test Suite 'Tests.xctest' started at 2020-10-19 16:53:56.014
Test Suite 'NSURLSessionTests' started at 2020-10-19 16:53:56.014
Test Case '-[NSURLSessionTests testWithRequest]' started.
2020-10-19 16:53:56.016936+0900 xctest[91856:6495007] Start: LocalDataTask <A9DFF949-ED27-4C5E-8E15-93113442D876>.<1>
如果我将nil
传递给delegateQueue
,它将按预期工作。
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:nil];
但不在主线程上。
Test Suite 'Selected tests' started at 2020-10-19 17:10:03.227
Test Suite 'Tests.xctest' started at 2020-10-19 17:10:03.228
Test Suite 'NSURLSessionTests' started at 2020-10-19 17:10:03.228
Test Case '-[NSURLSessionTests testWithRequest]' started.
2020-10-19 17:10:03.230845+0900 xctest[91910:6506707] Start: LocalDataTask <44C2D9FA-09D3-4C25-9129-B164D451836D>.<1>
2020-10-19 17:10:03.629414+0900 xctest[91910:6506750] didReceiveResponse: <NSThread: 0x7f8d2281f480>{number = 2,name = (null)}
2020-10-19 17:10:03.629867+0900 xctest[91910:6506750] <NSHTTPURLResponse: 0x7f8d20f333e0> { URL: http://example.com/ } { Status Code: 200,Headers {
...
} }
2020-10-19 17:10:03.630215+0900 xctest[91910:6506750] didReceiveData: <NSThread: 0x7f8d2281f480>{number = 2,name = (null)}
2020-10-19 17:10:03.630459+0900 xctest[91910:6506750] #NSData 1KB(1256)
2020-10-19 17:10:03.630940+0900 xctest[91910:6506750] didCompleteWithError: <NSThread: 0x7f8d2281f480>{number = 2,name = (null)}
2020-10-19 17:10:03.631095+0900 xctest[91910:6506750] (null)
Test Case '-[NSURLSessionTests testWithRequest]' passed (0.403 seconds).
Test Suite 'NSURLSessionTests' passed at 2020-10-19 17:10:03.632.
Executed 1 test,with 0 failures (0 unexpected) in 0.403 (0.404) seconds
Test Suite 'Tests.xctest' passed at 2020-10-19 17:10:03.633.
Executed 1 test,with 0 failures (0 unexpected) in 0.403 (0.405) seconds
Test Suite 'Selected tests' passed at 2020-10-19 17:10:03.633.
Executed 1 test,with 0 failures (0 unexpected) in 0.403 (0.406) seconds
Program ended with exit code: 0
为什么不使用[NSOperationQueue mainQueue]
来调用代表团?我如何在主线程上工作?
2020/10/23编辑
如前所述,当我改为XCTestExpectation
而不是dispatch_semaphore_t
时,Xctest代码起作用了。
@interface NSURLSessionTests : XCTestCase<NSURLSessionDataDelegate>
{
@private
XCTestExpectation *_expection;
}
@end
@implementation NSURLSessionTests
- (void)testWithRequest{
_expection = [self expectationWithDescription:@"UIDocument is opened."];
NSMutableuRLRequest *request = [NSMutableuRLRequest requestWithURL:[NSURL URLWithString: @"http://example.com/"]];
...
[dataTask resume];
[self waitForExpectations:[NSArray arrayWithObject:_expection] timeout:12.0];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"didCompleteWithError: %@",NSThread.currentThread);
NSLog(@"%@",error);
[_expection fulfill];
}
@end
但是我的应用代码仍然无法正常工作。当我检查应用程序代码时,发现正在等待HTTP请求结束。
- (void)startSync
{
FcLicenseChecker *license = [FcLicenseChecker sharedInstance];
if(!license.isCheckRunning)
{
[license execute];
}
[license waitUntilCheckFinished];
...
@implementation FcLicenseChecker
- (void)waitUntilCheckFinished
{
while (_isCheckRunning)
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
...
_isCheckRunning = NO;
}
它正在waitUntilCheckFinished
中肆虐,而没有代表团的来信。
我认为使用[NSRunLoop currentRunLoop] runUntilDate
等待结束的方式适用于NSURLConnection
的委派,但不适用于NSURLSession
。
我认为更改为在didCompleteWithError
中启动下一个进程而不是等待结束是可行的,但是这非常困难,因为有很多代码使用此类。
有没有办法等到NSURLSession
结束?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。