(AGGIORNATO) questo è il problema in poche parole: in iOS voglio leggere un file di grandi dimensioni, elaborarlo su di esso (in questo caso codificare come Base64 string() e salvare in un file temporaneo sul dispositivo. ho messo su un NSInputStream di leggere da un file, poi nelNSInputStream interrompe l'esecuzione, a volte genera EXC_BAD_ACCESS
(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
sto facendo la maggior parte del lavoro. per qualche ragione, a volte posso vedere il NSInputStream appena si ferma Lo so perché ho una linea
NSLog(@"stream %@ got event %x", stream, (unsigned)eventCode);
all'inizio del (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
ea volte vorrei solo vedere il risultato
stream <__NSCFInputStream: 0x1f020b00> got event 2
(che corrisponde all'evento NSStreamEventHasBytesAvailable) e quindi nulla dopo. Non evento 10, che corrisponde a NSStreamEventEndEncountered, non a un evento di errore, niente! E a volte ho anche ottenuto un'eccezione EXC_BAD_ACCESS che non ho idea al momento come eseguire il debug. Qualsiasi aiuto sarebbe apprezzato.
Ecco l'implementazione. Tutto inizia quando mi ha colpito un pulsante "invia", che innesca:
- (IBAction)submit:(id)sender {
[p_spinner startAnimating];
[self performSelector: @selector(sendData)
withObject: nil
afterDelay: 0];
}
Ecco 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] ;
}
Qui è setUpStreamsForInputFile chiama sopra:
- (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];
}
Infine, è qui più logica si verifica:
- (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:{
...
}
}
}
Nota: quando ho inviato questo messaggio per la prima volta, avevo l'impressione sbagliata che il problema riguardasse l'utilizzo di GCD. Come da risposta di Rob qui sotto ho rimosso il codice GCD e il problema persiste.
Grazie, LombaX. Solo per essere sicuro di capire quello che stai dicendo. Nella mia domanda iniziale, stavo dipingendo "sendData" a dispatch_async (dispatch_get_global_queue (0, 0) ... e poi quando stavo impostando il flusso per leggere dal file stavo usando dispatch_async (dispatch_get_main_queue() ... You ' sto dicendo di mantenere entrambi e basta aggiungere [[NSRunLoop currentRunLoop] run]? Non sono sicuro di seguire la logica, quindi penso di essere più sicuro ... grazie mille! – PeterD
è questo che intendevi? '- (void) setUpStreamsForInputFile : (NSString *) INPATH fileOutput: (NSString *) OUTPATH { \t self.p_iStream = ... \t [p_iStream setDelegate: self]; \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
E questo: ' - (IBAction) invia: (id) mittente { [p_spinner startAnimating]; dispatch_queue_t queue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async (coda,^{ [self sendData]; ** [[NSRunLoop currentRunLoop] run]; **}); } Mi dispiace per essere ottuso .. :) – PeterD