2010-07-16 34 views
1

我在学习如何使用单元测试在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

回答

0

它应是运行的循环被阻断由于单元测试正在执行的原因。您可以参考the NSRunLoop documentation,其中方法

runUntilDate: 

可能会帮助你运行像这样的单元测试的执行线程的主运行循环:

[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 

这让运行循环运行的1秒给它时间来处理你的文件的一部分。应该指出的是,这不能为单元测试提供可靠的方法(因为时间间隔可能因运行循环大小而异),因此可能不适用。通过给您的单元,其可用于检查输入流的状态的接口的读取操作(用读取结束状态),诸如

-(BOOL)hasFinishedReadingFile 

单元测试可以重复执行运行循环,直到上述方法返回TRUE并且文件被完全读取。

增加:This question on stackoverflow也以不同的方式处理问题。