2013-01-23 13 views
8

Ho un metodo come questo:Qual è il modo giusto per impostare un outparam NSError all'interno di un blocco autoreleasepool?

- (void)processAThing:(id)thing error:(NSError * __autoreleasing *)error 
{ 
    @autoreleasepool { 

      // Start processing. 

      // Find some partway through error.. 
      if (error) { 
       *error = [NSError errorWithDomain...]; 
       return NO; 
      } 

      // More processing. 
    } 
} 

Questa è rotto e va in crash, perché la NSError è autoreleased, e quando il ritorno accade, la piscina è svuotata, quindi la cosa che il chiamante si è ora fasullo.

So che potrei ridisegnare in modo significativo il metodo in modo da raccogliere tutti i casi di errore al di fuori del blocco di autorelease, ma voglio capire se c'è un modo corretto di gestire l'oggetto errore in questa situazione. Non riesco ad allocare/avviare un NSError speculativo al di fuori del blocco del pool, poiché le proprietà del dominio e del codice sono in sola lettura (e continuo a pensare che il riferimento scompaia al ritorno del metodo).

Risolve il problema se cambio la dichiarazione di metodo a questo:

- (void)processAThing:(id)thing error:(NSError * __strong *)error 

Ma poi ho bisogno di agitarsi intorno al luogo di chiamata in modo non standard, e questo sembra egregio per rendere il chiamante paga il prezzo per il mio autoreleasepool interno.

Qualche idea? Grazie.

+0

Cambiare la firma in '(NSError * __strong *) error' sembra davvero un'alternativa ragionevole per me. – Poulsbo

risposta

7

Ho avuto questo problema me stesso. In questo caso, penso che sia sufficiente dichiarare un nuovo riferimento forte appena prima dello @autoreleasepool e impostare l'argomento del metodo subito dopo il blocco @autoreleasepool da quel riferimento temporaneo.

- (void)processAThing:(id)thing error:(NSError * __autoreleasing *)error { 
    __strong NSError *errOut = nil; 
    @autoreleasepool { 
    // do your stuff and set errOut instead of error 
    } 
    if (error) { 
    *error = errOut; 
    } 
} 

(digitato sul browser, non errore controllato da compilatore)

Per quanto riguarda il ritorno prematuro, credo che si dovrà utilizzare un'etichetta di salto (anche se non è abbastanza).

+0

non è necessario scrivere '__strong'. È quello per impostazione predefinita – newacct

+1

Sì, l'ho messo lì solo per chiarire. –

+0

Grazie Erik. Sembra che non ci siano altri schemi ovvi da usare se non riducendo al minimo l'ambito del blocco di autorelease e impostando l'outparam al di fuori di esso. –

Problemi correlati