AFMultipartBodyStream不支持scheduleInRunLoop机制的原因是什么?

时间:2018-08-04 14:44:38

标签: objective-c afnetworking

尽管AFMultipartBodyStream的{​​{1}}是AFNetworking的子类,符合NSStream协议,但无法像常规{{1} }。即,NSStreamDelegate无法用流事件处理。我查看了NSStream的代码,发现它有意禁用了AFMultipartBodyStream抽象类的scheduleInRunLoop方法:

AFMultipartBodyStream

任何具体原因?是否有一种使其支持标准流事件机制的方法,以便可以使用stream:handleEvent:事件处理程序异步完成流数据处理?

1 个答案:

答案 0 :(得分:0)

研究完AFMultipartBodyStream的实现后,我注意到当前的实现方式无法支持常规流IO处理的异步方式。然后,我增强了AFMultipartBodyStream的功能,以提供一个与内部多部分数据结构连接的流,因此,该AFMultipartBodyStream的所有者可以将多部分数据作为常规流处理,可以在运行循环中对其进行调度。下面的代码段显示了主要思想:

-(NSInputStream *)inputStream {
    // If _inputStream has not been connected with HTTPBodyParts data, establish the connection
    if (!_inputStream) {
        NSParameterAssert([self.HTTPBodyParts count] != 0);
        CFReadStreamRef readStream;
        CFWriteStreamRef writeStream;
        CFIndex bufferSize = self.contentLength;
        CFStreamCreateBoundPair(NULL, &readStream, &writeStream, bufferSize);
        _inputStream = (__bridge_transfer NSInputStream *)readStream;
        _outputStream = (__bridge_transfer NSOutputStream *)writeStream;
        [_outputStream setDelegate:self];

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            NSLog(@"\n====in async block of inputStream....====\n");

            [self->_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [self open];
            [self->_outputStream open];
            NSInteger totalBytesSent = self.contentLength;
            while (totalBytesSent > 0 && [self->_outputStream hasSpaceAvailable]) {
                uint8_t buffer[1024];
                NSInteger bytesRead = [self read:buffer maxLength:1024];
                totalBytesSent -= bytesRead;
                NSLog(@"\n====buffer read (%ld): [%s]====\n", (long)bytesRead, buffer);
                if (self.streamError || bytesRead < 0) {
                    break;
                }

                NSInteger bytesWritten = [self->_outputStream write:buffer maxLength:(NSUInteger)bytesRead];
                if (self->_outputStream.streamError || bytesWritten < 0) {
                    NSLog(@"\n====Socket write failed[%@]====\n", self->_outputStream.streamError);
                    break;
                }

                if (bytesRead == 0 && bytesWritten == 0) {
                    break;
                }
            }

            [self->_outputStream close];
            [self->_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        });
    }

    return _inputStream;
}




// Added
- (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
                  forMode:(__unused NSString *)mode
{
    // Setup the input stream for body stream data consuming
    NSInputStream *inputStream = [self inputStream];
    NSParameterAssert(inputStream == self.inputStream);
    [inputStream setDelegate:self.delegate_];
    [inputStream scheduleInRunLoop:aRunLoop forMode:mode];
    [inputStream open];
}
// Added
- (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
                  forMode:(__unused NSString *)mode
{
    if (_inputStream) {
        [_inputStream setDelegate:[self delegate]];
        [_inputStream removeFromRunLoop:aRunLoop forMode:mode];
        [_inputStream close];
    }
}