(更新)これは一言で言えば問題です: iOS では、大きなファイルを読み取り、その上で何らかの処理を行いたい (この特定のケースでは、Base64 string() としてエンコードし、デバイス上の一時ファイルに保存します。セットアップしますファイルから読み込む NSInputStream
(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 に対応します)、その後は何もありません。NSStreamEventEndEncountered に対応するイベント 10 ではなく、エラー イベントでもありません。また、時にはデバッグ方法がわからない EXC_BAD_ACCESS 例外が発生することもあります。どんな助けでも大歓迎です。
これが実装です。「送信」ボタンを押すとすべてが開始され、トリガーされます。
- (IBAction)submit:(id)sender {
[p_spinner startAnimating];
[self performSelector: @selector(sendData)
withObject: nil
afterDelay: 0];
}
sendData は次のとおりです。
-(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コードを削除しましたが、問題は解決しません。