Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Gestione della Memoria: ARC

Come viene gestita (automaticamente) la memoria di un'applicazione scritta in Objective C, sfruttando il meccanismo di garbage collection introdotto con ARC.
Come viene gestita (automaticamente) la memoria di un'applicazione scritta in Objective C, sfruttando il meccanismo di garbage collection introdotto con ARC.
Link copiato negli appunti

Nel 2011 Apple ha reso disponibile per Objective-C un meccanismo per la gestione della memoria chiamato Automatic Reference Counting, o più semplicemente ARC. Tale meccanismo permette di gestire la memoria in maniera trasparente allo sviluppatorestrong>, contrariamente a quanto avveniva in precedenza (quando, cioè, la memoria doveva essere gestita manualmente).

ARC associa un contatore (reference count) ad ogni oggetto, in modo da tenere traccia delle referenze all’oggetto stesso. Quando il numero di referenze a un certo oggetto scende a 0, allora la memoria occupata dall’oggetto viene liberata.

ARC offre 3 importanti vantaggi rispetto al Garbage Collector di Java:

  1. la dimensione del footprint dell’applicazione (ovvero lo spazio di memoria principale assegnato all'applicazione) è ridotto. Al contrario del Garbage Collector, che provoca un accumularsi di memoria occupata finché non viene eseguito, ARC libera la memoria associata a un oggetto non appena questo non è più referenziato;
  2. il footprint è deterministico. Questo significa che se eseguiamo un'app varie volte e immettiamo gli stessi input, l’andamento dell’occupazione in memoria sarà sempre lo stesso;
  3. ARC non sovraccarica il sistema. In Java l’esecuzione del Garbage Collector provoca una saturazione delle risorse hardware che nei casi peggiori possono anche essere percepiti dall’utente come un rallentamento dell’applicazione. ARC libera memoria man mano che questa non è più necessaria, senza provocare picchi in cui le risorse del sistema sono sature.

Vediamo ora ARC in azione. Prima di tutto, creiamo 2 classi (Book e Author) come mostrato di seguito.

File Author.h

#import <Foundation/Foundation.h>
@interface Author : NSObject
- (instancetype)initWithName:(NSString*)name;
@property (retain, readonly) NSString * name;
@end

File Author.m

@implementation Author
- (instancetype)initWithName:(NSString*)name {
    if (self = [super init]) {
        _name = name;
    }
    return self;
}
-(void)dealloc {
    NSLog(@"did dealloc author");
}
@end

File Book.h

#import <Foundation/Foundation.h>
#import "Author.h"
@interface Book : NSObject
- (instancetype)initWithTitle:(NSString*)title;
@property (retain, readwrite) NSString * title;
@property (retain, readwrite) Author * author;
@end

File Book.m

#import "Book.h"
@implementation Book
- (instancetype)initWithTitle:(NSString*)title {
    if (self = [super init]) {
        _title = title;
    }
    return self;
}
- (void)dealloc {
    NSLog(@"did dealloc book");
}
@end

Il metodo dealloc che abbiamo aggiunto ad entrambe le classi viene invocato automaticamente quando la classe viene deallocata. In questo modo, se vedremo nel log le stringhe did dealloc book o did dealloc author avremo la sicurezza che gli oggetti sono stati rimossi dalla memoria.

Tornado ora al file main.m e modifichiamolo come mostrato di seguito:

@import Foundation;
#import "Author.h"
#import "Book.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        for (int i = 0; i < 3; i++) {
            NSLog(@"Start loop");
            Book * book = [[Book alloc] initWithTitle:@"The Naked Sun"];
            book.author = [[Author alloc] initWithName:@"Isaac Asimov"];
            NSLog(@"End loop");
        }
    }
    return 0;
}

Il ciclo for viene ripetuto 3 volte, ed ogni volta creiamo un Book ed aggiungiamo ad esso un Author. Dal punto di vista della memoria, abbiamo una situazione di questo tipo:

All’interno del codice abbiamo una referenza all’oggetto Book, che a sua volta ha una referenza all’oggetto Author. Di conseguenza, finché ci troviamo all’interno del ciclo for, il reference count di Book è pari a 1, così come quello di Author.

Appena usciamo dallo scope del ciclo for, il reference count di Book scende a 0. Quindi automaticamente le sue properties vengono impostate a nil. Questo porta il reference count di Author a 0. Quindi sia Book che Author vengono deallocati.

Facciamo girare il codice e osserviamo la console:

Start loop
 End loop
 did dealloc book
 did dealloc author
 Start loop
 End loop
 did dealloc book
 did dealloc author
 Start loop
 End loop
 did dealloc book
 did dealloc author

Vediamo chiaramente che subito dopo la stampa di End loop, appena la variabile Book esce dallo scope, vengono deallocati entrambi gli oggetti Book e Author.

Ti consigliamo anche