NSInputStream wird nicht mehr ausgeführt und löst manchmal EXC_BAD_ACCESS aus

(AKTUALISIERTE) Das ist das Problem auf den Punkt gebracht: Unter iOS möchte ich eine große Datei lesen, etwas bearbeiten (in diesem Fall als Base64-Zeichenfolge codieren () und in einer temporären Datei auf dem Gerät speichern. Ich habe einen NSInputStream für eingerichtet Aus einer Datei lesen, dann in

(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode

Ich mache den größten Teil der Arbeit. Aus irgendeinem Grund sehe ich manchmal, dass der NSInputStream einfach nicht mehr funktioniert. Ich weiß, weil ich eine Leitung habe

NSLog(@"stream %@ got event %x", stream, (unsigned)eventCode);

am anfang von(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode und manchmal würde ich nur die Ausgabe sehen

stream <__NSCFInputStream: 0x1f020b00> got event 2

(was dem Ereignis NSStreamEventHasBytesAvailable entspricht) und danach nichts mehr. Kein Ereignis 10, das NSStreamEventEndEncountered entspricht, kein Fehlerereignis, nichts! Und manchmal bekomme ich sogar eine EXC_BAD_ACCESS-Ausnahme, von der ich im Moment keine Ahnung habe, wie ich debuggen soll. Jede Hilfe wäre dankbar.

Hier ist die Implementierung. Alles beginnt, wenn ich einen "Submit" -Button drücke, der Folgendes auslöst:

- (IBAction)submit:(id)sender {     
    [p_spinner startAnimating];    
    [self performSelector: @selector(sendData)
           withObject: nil
           afterDelay: 0];   
}

Hier ist 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] ;
}

Hier ist setUpStreamsForInputFile wie oben beschrieben:

- (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];   
}

Schließlich ist dies der Punkt, an dem die meiste Logik auftritt:

- (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:{
            ...
        }
    }
}

Hinweis: Als ich das erste Mal gepostet habe, hatte ich den falschen Eindruck, dass das Problem mit der Verwendung von GCD zu tun hat. Laut Robs Antwort unten habe ich den GCD-Code entfernt und das Problem bleibt bestehen.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage