(更新)這是一個簡單的問題:在iOS中我想讀一個大文件,對它做一些處理(在這種情況下編碼爲Base64 string()和保存到設備上的臨時文件。我建立了一個NSInputStream從文件中讀取,然後在NSInputStream停止運行,有時會拋出EXC_BAD_ACCESS
(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
我做的大部分工作。出於某種原因,有時候我可以看到NSInputStream只是停止我知道,因爲我有一條線
NSLog(@"stream %@ got event %x", stream, (unsigned)eventCode);
在(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
開始,有時我只想看到輸出
stream <__NSCFInputStream: 0x1f020b00> got event 2
(對應於事件NSStreamEventHasBytesAvailable)然後就沒有後來。不是事件10,它對應於NSStreamEventEndEncountered,不是一個錯誤事件,沒有!有時候我甚至會得到一個EXC_BAD_ACCESS異常,我現在還不知道如何調試。任何幫助,將不勝感激。
這是實施。一切開始時我打了 「提交」 按鈕,觸發:
- (IBAction)submit:(id)sender {
[p_spinner startAnimating];
[self performSelector: @selector(sendData)
withObject: nil
afterDelay: 0];
}
這裏是送出數據:
-(void)sendData{
...
_tempFilePath = ... ;
[[NSFileManager defaultManager] createFileAtPath:_tempFilePath contents:nil attributes:nil];
[self setUpStreamsForInputFile: [self.p_mediaURL path] outputFile:_tempFilePath];
[p_spinner stopAnimating];
//Pop back to previous VC
[self.navigationController popViewControllerAnimated:NO] ;
}
下面是setUpStreamsForInputFile稱爲上面:
- (void)setUpStreamsForInputFile:(NSString *)inpath outputFile:(NSString *)outpath {
self.p_iStream = [[NSInputStream alloc] initWithFileAtPath:inpath];
[p_iStream setDelegate:self];
[p_iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[p_iStream open];
}
最後,這是哪裏大多數邏輯發生:
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
NSLog(@"stream %@ got event %x", stream, (unsigned)eventCode);
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
if (stream == self.p_iStream){
if(!_tempMutableData) {
_tempMutableData = [NSMutableData data];
}
if ([_streamdata length]==0){ //we want to write to the buffer only when it has been emptied by the output stream
unsigned int buffer_len = 24000;//read in chunks of 24000
uint8_t buf[buffer_len];
unsigned int len = 0;
len = [p_iStream read:buf maxLength:buffer_len];
if(len) {
[_tempMutableData appendBytes:(const void *)buf length:len];
NSString* base64encData = [Base64 encodeBase64WithData:_tempMutableData];
_streamdata = [base64encData dataUsingEncoding:NSUTF8StringEncoding]; //encode the data as Base64 string
[_tempFileHandle writeData:_streamdata];//write the data
[_tempFileHandle seekToEndOfFile];// and move to the end
_tempMutableData = [NSMutableData data]; //reset mutable data buffer
_streamdata = [[NSData alloc] init]; //release the data buffer
}
}
}
break;
case NSStreamEventEndEncountered:
{
[stream close];
[stream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
stream = nil;
//do some more stuff here...
...
break;
}
case NSStreamEventHasSpaceAvailable:
case NSStreamEventOpenCompleted:
case NSStreamEventNone:
{
...
}
}
case NSStreamEventErrorOccurred:{
...
}
}
}
注意:當我第一次發佈時,我的印象是錯誤的,這個問題與使用GCD有關。根據Rob的回答,我刪除了GCD代碼,問題依然存在。
謝謝,LombaX。只是爲了確保我明白你在說什麼。在我原來的問題中,我正在將dispatch_async(dispatch_get_global_queue(0,0)...)設置爲dispatch_async(dispatch_get_main_queue()...),然後當我設置流從文件中讀取時,我不知道我遵循的邏輯,所以我認爲我更好地確保...非常感謝! – PeterD 2013-03-11 19:07:49
這是你的意思嗎? ' - (void)setUpStreamsForInputFile :(的NSString *)INPATH OUTPUTFILE:(的NSString *)outpath中{ \t self.p_iStream = ... \t [p_iStream setDelegate:自]; \t dispatch_async(dispatch_get_main_queue(),^ { \t \t [p_iStream scheduleInRunLoop: NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; \t \t [p_iStream open]; \t \t ** [[NSRunLoop currentRunLoop] run]; ** \t}); } – PeterD 2013-03-11 19:24:01
並且這個: ' - (IBAction)提交:(id)發送者{p_spinner startAnimating]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); dispatch_async(queue,^ {self-sendData]; ** [[NSRunLoop currentRunLoop] run]; **}); }' 對不起,我正在修改.. :) – PeterD 2013-03-11 19:24:19