尽管AFMultipartBodyStream
的{{1}}是AFNetworking
的子类,符合NSStream
协议,但无法像常规{{1} }。即,NSStreamDelegate
无法用流事件处理。我查看了NSStream
的代码,发现它有意禁用了AFMultipartBodyStream
抽象类的scheduleInRunLoop方法:
AFMultipartBodyStream
任何具体原因?是否有一种使其支持标准流事件机制的方法,以便可以使用stream:handleEvent:事件处理程序异步完成流数据处理?
答案 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];
}
}