2012-04-27 9 views
5

Sembra che nell'esempio di codice di un libro, il init sia sempre definito in modo che sia attento a verificare se è possibile esistere self.In Objective-C, come trattare con [[myView alloc] init] restituendo nil?

-(id) init { 

    self = [super init]; 
    if (self) { 
     // initialize 
    } 
    return self; 
} 

Tuttavia, al momento del ritorno, nessuno del codice controlla se l'oggetto è in grado di esistere. Ma dovrebbe essere controllato, e come può essere gestito? Se l'oggetto non può esistere, vuol dire che il sistema è seriamente a corto di memoria, e anche spuntando un messaggio di errore sarà anche impossibile?

+0

Questa è davvero una buona domanda. So di non controllare mai se ottengo qualcosa dal risultato di questo tipo di funzione, presumo solo che alloc/init abbia funzionato (a meno che non si lavori con qualcosa che richiede & errore, che rappresenta qualcosa che ha una possibilità di fallire). Una domanda davvero interessante. – RonLugge

+0

possibile duplicato di [In Objective-C perché dovrei controllare se self = \ [super init \] non è nulla?] (Http://stackoverflow.com/questions/1287950/in-objective-c-why-should- i-check-if-self-super-init-is-not-nil) – omz

risposta

4

Tuttavia, al momento del ritorno, nessuno del codice controlla se l'oggetto è in grado di esistere. Ma dovrebbe essere controllato, e come può essere gestito?

In genere, la gestione degli errori viene ignorata dalle sottoclassi quando viene restituito nil. La gestione degli errori viene generalmente lasciata al chiamante quando viene restituito nil. Come dimostrato nella idiomatica -init:

- (id)init { 
    self = [super init]; 
    if (self) { 
    // initialize 
    } 
    return self; 
} 

Così, se la base rialloca self in init, quindi self viene riassegnato (self = [super init];). funziona alla grande.

Se non si riesce ad assegnare self al risultato di inizializzazione super s' o se non si riesce a verificare la presenza di nil, allora si può essere aggrappandosi ad una penzoloni/puntatore deallocato (EXC_BAD_ACCESS), e non si può inizializzare le ivars correttamente (assegneresti effettivamente a un'altra area se non si incontra uno EXC_BAD_ACCESS).

I due casi in modo più dettagliato:

non riescono ad assegnare sé

- (id)init { 
    [super init]; 
    if (self) { 
    // self was not reassigned. if super returned an object other 
    // than self, then our ivar would be freed, reused, or sitting 
    // in an autorelease pool, and the returned instance's ivar 
    // would not be assigned -- we wouldn't know the address. 
    ivar = 1; 
    } 
    return self; 
} 

non riescono a controllare per nil

- (id)init { 
    self = [super init]; 
    // super returned nil. ivar is an invalid region: 
    ivar = 1; 
    return self; 
} 

e sì, ho visto entrambi queste.


Se l'oggetto non può esistere, significa che il sistema è seriamente la memoria, e persino spuntando un messaggio di errore sarà anche impossibile?

Niente affatto. Molti inizializzatori restituiscono nil per dire "impossibile fare in questo contesto", o se c'è un semplice errore di parametro.

+0

Scusa, non capisco come avresti un puntatore penzolante se non controlli nulla. Se non si controlla nulla, si invierà effettivamente messaggi a zero se un zero dovesse venire e verrebbero ignorati. – borrrden

+0

Ah, vedo che è in realtà la seconda parte (auto di riassegnazione) di cui stai parlando. Nevermind ^^; – borrrden

+0

@borrrden vedo che hai visto l'aggiornamento che ho fatto per te :) sì, la messaggistica * potrebbe * essere al sicuro, se il tuo ego fosse zero e tu avresti inviato un messaggio nel tuo inizializzatore. tuttavia, l'inizializzazione e dealloc sono stati speciali parzialmente costruiti. le persone sostengono entrambe le parti, ma l'inizializzazione diretta è generalmente il modo più sicuro per inizializzare un oggetto, piuttosto che usare i metodi di accesso in init/dealloc. Anche la mancata verifica di nil è un rischio, come dimostrato. – justin

3

significa che il sistema è seriamente di memoria

No. La mancata allocare memoria essi generalmente provocare + alloc fallire, non -init.

In realtà, è molto raro che un metodo init senza argomenti fallisca. Generalmente i metodi init possono restituire nil se hai passato argomenti non validi, ad esempio Nittring's -initWithContentsOfFile: può restituire nil se non è riuscito a caricare il contenuto del percorso del file con il quale si supponeva fosse inizializzato.

È forse qualcosa che si desidera controllare se si è a conoscenza di una possibilità significativa per il fallimento di init, altrimenti, si dovrebbe semplicemente andare avanti con l'uso dell'oggetto.

+0

Inoltre, su iOS, se il sistema è seriamente fuori dalla memoria, si verrà scaricati. –

+0

@KevinBallard, sì, l'app verrà uccisa prima che un'allocazione di memoria fallisca. E su OS X, c'è un enorme spazio di memoria virtuale a 64 bit che è praticamente impossibile che un'app esaurisca la memoria. – joerick

+0

iOS utilizzerà la memoria Flash lasciata come memoria virtuale? (ad esempio se l'iPhone da 16 GB ha 3 GB gratuiti) ... tuttavia, il mio iPhone è così pieno di canzoni a causa del download automatico che solo 20 MB sono gratuiti. –

Problemi correlati