带委托的NSURLSession在主线程上不起作用

如何解决带委托的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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?