O ARC é apenas reproduzir a retenção / liberação antiga (MRC) com o compilador descobrindo quando chamar reter / liberar. Ele tenderá a ter um desempenho mais alto, menor uso de memória de pico e desempenho mais previsível que um sistema de GC.
Por outro lado, alguns tipos de estrutura de dados não são possíveis com o ARC (ou MRC), enquanto o GC pode lidar com eles.
Como exemplo, se você tiver uma classe denominada nó, e o nó tiver um NSArray de filhos e uma única referência ao pai, que "simplesmente funciona" com o GC. Com o ARC (e também com a contagem manual de referências), você tem um problema. Qualquer nó será referenciado de seus filhos e também de seu pai.
Gostar:
A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A
Tudo está bem enquanto você estiver usando A (digamos, através de uma variável local).
Quando você terminar com ele (e B1 / B2 / B3), um sistema de GC decidirá, eventualmente, examinar tudo o que encontrar, iniciando nos registros da pilha e da CPU. Ele nunca encontrará A, B1, B2, B3, finalizando-os e reciclando a memória em outros objetos.
Quando você usa ARC ou MRC, e termina com A, ele tem uma refcount de 3 (B1, B2 e B3 todos fazem referência a ele), e B1 / B2 / B3 terá todos uma contagem de referência de 1 (o NSArray de A mantém uma referência a cada). Portanto, todos esses objetos permanecem vivos, mesmo que nada possa usá-los.
A solução comum é decidir que uma dessas referências precisa ser fraca (não contribua para a contagem de referências). Isso funcionará para alguns padrões de uso, por exemplo, se você referenciar B1 / B2 / B3 apenas via A. No entanto, em outros padrões, ele falha. Por exemplo, se você às vezes se apegar a B1 e esperar subir de volta pelo ponteiro pai e encontrar A. Com uma referência fraca, se você se apegar a B1, A pode (e normalmente irá) evaporar e pegar B2 e B3 com isso.
Às vezes, isso não é um problema, mas algumas maneiras muito úteis e naturais de trabalhar com estruturas complexas de dados são muito difíceis de usar com o ARC / MRC.
Portanto, o ARC visa o mesmo tipo de problemas que o GC almeja. No entanto, o ARC trabalha com um conjunto mais limitado de padrões de uso que o GC; portanto, se você pegasse uma linguagem GC (como Java) e enxertasse algo como ARC nela, alguns programas não funcionariam mais (ou pelo menos gerariam toneladas de memória abandonada) , e pode causar sérios problemas de troca ou ficar sem memória ou trocar espaço).
Você também pode dizer que o ARC coloca uma prioridade maior no desempenho (ou talvez previsibilidade), enquanto o GC coloca uma prioridade maior em ser uma solução genérica. Como resultado, o GC possui demandas de CPU / memória menos previsíveis e um desempenho mais baixo (normalmente) que o ARC, mas pode lidar com qualquer padrão de uso. O ARC funcionará muito melhor para muitos padrões de uso comuns, mas para alguns padrões de uso (válidos!), Ele cairá e morrerá.