在OCUnitTest中无法接收NSInputStream事件
问题描述:
我在学习如何使用单元测试在iPhone上使用NSInputStream类。我可以让NSStream使用轮询方法从文件中读取数据,但由于某种原因委托/事件方法不起作用。在OCUnitTest中无法接收NSInputStream事件
我已经发布了下面的相关代码。请忽略内存泄漏错误等,因为我只是试图确保我知道如何在沙盒环境中使用NSStream类,然后将其滚动到我的大型项目中。
我想知道如果我错过了一些关于运行循环如何工作的东西?
这是创建流文件类以从文件读取的逻辑测试。
#import "StreamingTests.h"
#import "Streamer.h"
@implementation StreamingTests
- (void) testStream {
NSLog(@"Starting stream test.");
Streamer * streamer = [[Streamer alloc] init];
streamer.usePolling = NO;
streamer.readingStream = YES;
NSThread * readThread = [[NSThread alloc] initWithTarget:streamer selector:@selector(startStreamRead:) object:nil];
[readThread start];
while(streamer.readingStream) {
[NSThread sleepForTimeInterval:0.5];
}
[readThread cancel];
}
@end
这是一个简单的测试辅助对象,其从NSStream读取。当usePolling == YES时,它读取数据并输出适当的NSLog消息。但是,如果usePolling == NO,则从不调用委托流事件函数。
@implementation Streamer
@synthesize readingStream, usePolling;
- (void) startStreamRead:(NSObject*) context {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"starting stream read.");
readingStream = YES;
/*
NSURL * url = [NSURL URLWithString:@"http://www.google.com"];
NSLog(@"Loading: %@",[url description]);
NSInputStream * inStream = [[NSInputStream alloc] initWithURL:url];
*/
NSInputStream * inStream = [[NSInputStream alloc] initWithFileAtPath:@"sample.ttc"];
if(!usePolling) {
[inStream setDelegate: self];
[inStream scheduleInRunLoop: [NSRunLoop currentRunLoop]
forMode: NSDefaultRunLoopMode];
}
[inStream open];
if(usePolling) {
while(1) {
if([inStream hasBytesAvailable]) {
uint8_t buf[1024];
unsigned int len = 0;
len = [(NSInputStream *)inStream read:buf maxLength:1024];
NSLog(@"Read: %d",len);
}
NSStreamStatus status = [inStream streamStatus];
if(status != NSStreamStatusOpen && status != NSStreamStatusOpening) {
NSLog(@"Stream not open.");
break;
}
}
readingStream = NO;
NSStreamStatus status = [inStream streamStatus];
NSError * error = [inStream streamError];
NSLog(@"Status: %d Error Desc: %@ Reason: %@",(int)status,[error localizedDescription], [error localizedFailureReason]);
[pool release];
}
}
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
NSMutableData * _data = nil;
NSNumber * bytesRead = nil;
NSLog(@"Event fired.");
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
if(!_data) {
_data = [[NSMutableData data] retain];
}
uint8_t buf[1024];
unsigned int len = 0;
len = [(NSInputStream *)stream read:buf maxLength:1024];
if(len) {
[_data appendBytes:(const void *)buf length:len];
// bytesRead is an instance variable of type NSNumber.
//[bytesRead setIntValue:[bytesRead intValue]+len];
NSLog(@"Read %d bytes",len);
} else {
NSLog(@"no buffer!");
}
break;
}
case NSStreamEventEndEncountered:
{
[stream close];
[stream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[stream release];
stream = nil; // stream is ivar, so reinit it
readingStream = NO;
break;
}
default:
{
NSLog(@"Another event occurred.");
break;
}
// continued ...
}
}
@end
由于提前,
b
答
它应是运行的循环被阻断由于单元测试正在执行的原因。您可以参考the NSRunLoop documentation,其中方法
runUntilDate:
可能会帮助你运行像这样的单元测试的执行线程的主运行循环:
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
这让运行循环运行的1秒给它时间来处理你的文件的一部分。应该指出的是,这不能为单元测试提供可靠的方法(因为时间间隔可能因运行循环大小而异),因此可能不适用。通过给您的单元,其可用于检查输入流的状态的接口的读取操作(用读取结束状态),诸如
-(BOOL)hasFinishedReadingFile
单元测试可以重复执行运行循环,直到上述方法返回TRUE并且文件被完全读取。
增加:This question on *也以不同的方式处理问题。