ARC è solo il vecchio Mantieni / Rilascio (MRC) con il compilatore che capisce quando chiamare il blocco / rilascio. Tenderà ad avere prestazioni più elevate, un utilizzo di memoria di picco inferiore e prestazioni più prevedibili rispetto a un sistema GC.
D'altra parte alcuni tipi di strutture dati non sono possibili con ARC (o MRC), mentre GC può gestirli.
Ad esempio, se si dispone di una classe denominata nodo e il nodo ha un NSArray di figli e un singolo riferimento al suo genitore che "funziona" con GC. Con ARC (e anche il conteggio dei riferimenti manuali) hai un problema. Ogni nodo dato sarà referenziato dai suoi figli e anche dai suoi genitori.
Piace:
A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A
Tutto va bene mentre stai usando A (ad esempio tramite una variabile locale).
Quando hai finito (e B1 / B2 / B3), un sistema GC alla fine deciderà di guardare tutto ciò che può trovare a partire dallo stack e dai registri della CPU. Non troverà mai A, B1, B2, B3, quindi li finalizzerà e riciclerà la memoria in altri oggetti.
Quando si utilizza ARC o MRC e si termina con A, si ha un refcount di 3 (B1, B2 e B3 fanno tutti riferimento a esso) e B1 / B2 / B3 avrà tutti un conteggio di riferimento di 1 (l'array NS di A contiene un riferimento a ogni). Quindi tutti quegli oggetti rimangono vivi anche se nulla può mai usarli.
La soluzione comune è decidere che uno di quei riferimenti deve essere debole (non contribuire al conteggio dei riferimenti). Ciò funzionerà per alcuni schemi di utilizzo, ad esempio se si fa riferimento a B1 / B2 / B3 solo tramite A. Tuttavia, in altri schemi fallisce. Ad esempio, se a volte tieni premuto B1 e ti aspetti di risalire tramite il puntatore genitore e trovare A. Con un riferimento debole se tieni premuto B1, A può (e normalmente) evaporare e prendere B2 e B3 con esso.
A volte questo non è un problema, ma alcuni modi molto utili e naturali di lavorare con strutture complesse di dati sono molto difficili da usare con ARC / MRC.
Quindi ARC affronta lo stesso tipo di problemi target GC. Tuttavia ARC funziona su un set più limitato di schemi di utilizzo rispetto a GC, quindi se prendessi un linguaggio GC (come Java) e innesti qualcosa come ARC su di esso alcuni programmi non funzionerebbero più (o almeno genererebbero tonnellate di memoria abbandonata e può causare seri problemi di scambio o esaurire la memoria o lo spazio di scambio).
Puoi anche dire che ARC attribuisce una priorità maggiore alle prestazioni (o forse alla prevedibilità) mentre GC attribuisce una priorità maggiore all'essere una soluzione generica. Di conseguenza, GC ha requisiti CPU / memoria meno prevedibili e prestazioni (normalmente) inferiori rispetto ad ARC, ma può gestire qualsiasi modello di utilizzo. ARC funzionerà molto meglio per molti modelli di utilizzo comuni, ma per alcuni (validi!) Modelli di utilizzo cadrà e morirà.