2011-10-01 22 views
8

Ho il seguente codice. Occasionalmente ricevo un SIGSEGV. Ho la sensazione che mi manchi qualcosa riguardo alla gestione della memoria usando i blocchi. È sicuro passare gli URL sostituiti, che sono autorizzati a questo blocco? Che dire della modifica della variabile di istanza formattedText?Che cosa sta causando un SIGSEGV utilizzando i blocchi?

NSMutableSet* replacedUrls = [[[NSMutableSet alloc] init] autorelease]; 

    NSError *error = nil; 
    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes: 
           (NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber) 
                   error:&error]; 
    if (error) { 
     return; 
    } 

    [detector enumerateMatchesInString:self.formattedText 
       options:0 
       range:NSMakeRange(0, [self.formattedText length]) 
       usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 

      @try { 
       if (result.resultType == NSTextCheckingTypePhoneNumber) { 

        if (!result.phoneNumber) { 
         // not sure if this is possible 
         return; 
        } 

        self.formattedText = [self.formattedText stringByReplacingOccurrencesOfString:result.phoneNumber 
                         withString:[NSString stringWithFormat:@"<a href=\"tel://%@\">%@</a>", result.phoneNumber, result.phoneNumber]]; 
       } 
       else if (result.resultType == NSTextCheckingTypeLink) { 

        if (!result.URL) { 
         // not sure if this is possible 
         return; 
        } 

        NSString* fullUrl = [result.URL absoluteString]; 

        if (!fullUrl) { 
         return; 
        } 

        if ([replacedUrls containsObject:fullUrl]) { 
         return; 
        } 

        // not sure if this is possible 
        if ([result.URL host] && [result.URL path]) { 
         NSString* urlWithNoScheme = [NSString stringWithFormat:@"%@%@", [result.URL host], [result.URL path]]; 

         // replace all http://www.google.com to www.google.com 
         self.formattedText = [self.formattedText stringByReplacingOccurrencesOfString:fullUrl 
                          withString:urlWithNoScheme]; 

         // replace all www.google.com with http://www.google.com 
         NSString* replaceText = [NSString stringWithFormat:@"<a href=\"%@\">%@</a>", fullUrl, fullUrl]; 
         self.formattedText = [self.formattedText stringByReplacingOccurrencesOfString:urlWithNoScheme 
                          withString:replaceText]; 

         [replacedUrls addObject:fullUrl]; 
        } 
       } 
      } 
      @catch (NSException* ignore) { 
       // ignore any issues 
      } 
     }]; 
+0

Dopo alcune letture, sto sicuramente vedendo dove vorrei creare un ciclo di conservazione da quando sarebbe stato mantenuto. Ancora non sono sicuro di come ciò possa creare il problema attuale, però. – tjg184

+0

la riga più volgare è 'if (errore) {return;} ma non sono sicuro di come questo causi il tuo problema (il tuo codice recupera con grazia se ritorni a questo punto, giusto?). Il mantenimento del sé non causa necessariamente un ciclo di mantenimento e un ciclo di mantenimento non causerebbe un SIGSEGV; – hooleyhoop

+0

Sì, quella linea è strana. Non sono nemmeno sicuro che sia necessario. Penso di averlo aggiunto come controllo di sanità mentale. Stava ricevendo un SIGSEGV prima che aggiungessimo quella linea. La maggior parte di quelli se le istruzioni sono state aggiunte perché il rapporto di arresto anomalo puntava semplicemente al blocco generale e non a una linea specifica. Tipo di fastidio per rintracciare il problema. È sicuro modificare il formattedText in questo? – tjg184

risposta

2

Sembra che il problema riscontrato sia correlato alla gestione della memoria. Inizi a cercare attraverso la stringa self.formattedText. Ciò significa che, mentre questa ricerca ha luogo, l'istanza NSDataDetector probabilmente deve accedere alla stringa per leggere i caratteri, ecc. Funziona tutto bene e bene, purché self.formattedText non venga deallocato. Di solito, anche per metodi di blocco come questo, è responsabilità del chiamante mantenere gli argomenti fino alla fine della chiamata di funzione.

Quando, all'interno del blocco trovato corrispondenza, si modifica il valore di self.formattedText, il valore precedente viene rilasciato automaticamente (presupponendo che questa sia una proprietà retain). Non sono a conoscenza della memorizzazione nella cache di NSDataDetector, o dei problemi relativi ai pool di autorelease, ecc., Ma sono abbastanza sicuro che ciò potrebbe causare un problema.

il mio suggerimento è che si passa[NSString stringWithString:self.formattedText] come argomento enumerateMatchesInString:, piuttosto che la pianura self.formattedText. In questo modo, si passa a NSDataDetector un'istanza che non verrà rilasciata fino a quando il pool di autorelease non verrà scaricato.

+0

Non l'ho ancora testato, ma penso che la tua risposta sia degna. :) – tjg184

Problemi correlati