Para ARC ou não para ARC? Quais são os prós e contras?

Eu ainda tenho que usar o ARC, uma vez que a maioria do código no projeto que estou trabalhando no momento foi escrito pré-iOS 5.0.

Eu estava pensando, a conveniência de não reter / liberar manualmente (e presumivelmente o código mais confiável que vem como resultado?) Supera qualquer custo de usar o ARC? Quais são as suas experiências da ARC e você recomendaria?

Assim:

  • Quanto benefício a ARC pode trazer para um projeto?
  • O ARC tem um custo como garbage collection em Java?
  • Você tem usado o ARC e, em caso afirmativo, como você o encontrou até agora?

Não há desvantagem. Use-o. Faça hoje. É mais rápido que o seu código antigo. É mais seguro que seu código antigo. É mais fácil que seu código antigo. Não é garbage collection. Não tem sobrecarga de tempo de execução do GC. O compilador insere retenções e lançamentos em todos os lugares que você deve ter de qualquer maneira. Mas é mais inteligente do que você e pode otimizar os que não são realmente necessários (assim como pode desenrolar loops, eliminar variables ​​temporárias, funções inline, etc.)

OK, agora vou falar sobre as pequenas desvantagens:

  • Se você é um desenvolvedor de ObjC de longa data, vai se contorcer por cerca de uma semana quando vir o código ARC. Você vai superar isso rapidamente.

  • Existem algumas complicações (muito) pequenas na conexão com o código da Core Foundation. Há um pouco mais de complicações ao lidar com qualquer coisa que trate um id como um void* . Coisas como C-arrays of id podem demorar um pouco mais para serem feitas corretamente. A manipulação extravagante do ObjC va_args também pode causar problemas. A maioria das coisas envolvendo matemática em um ponteiro ObjC é mais complicada. Você não deve ter muito disso em qualquer caso.

  • Você não pode colocar um id em uma struct . Isso é bastante raro, mas às vezes é usado para compactar dados.

  • Se você não seguiu a nomenclatura correta do KVC e misturou o código ARC e não-ARC, você terá problemas de memory. O ARC usa a nomenclatura KVC para tomar decisões sobre o gerenciamento de memory. Se é todo o código ARC, então não importa, porque fará o mesmo “errado” em ambos os lados. Mas se é misturado ARC / não-ARC, então há uma incompatibilidade.

  • ARC irá vazar memory durante lançamentos de exceção ObjC. Uma exceção ObjC deve estar muito próxima ao término do seu programa. Se você está pegando um número significativo de exceções ObjC, você está usando-as incorretamente. Isso pode ser -fobjc-arc-exceptions usando -fobjc-arc-exceptions , mas incorre nas penalidades discutidas abaixo:

  • ARC não vazará memory durante a exceção ObjC ou C ++ lançada no código ObjC ++, mas isso é ao custo do tempo e do desempenho do espaço. Este é ainda outro em uma longa lista de razões para minimizar o uso de ObjC ++.

  • O ARC não funcionará no iPhoneOS 3 ou no Mac OS X 10.5 ou anterior. (Isso me impede de usar o ARC em muitos projetos.)

  • __weak pointers __weak não funcionam corretamente no iOS 4 ou no Mac OS X 10.6, o que é uma vergonha, mas bastante fácil de contornar. __weak pointers __weak são ótimos, mas eles não são o principal ponto de venda da ARC.

Para 95% + de código lá fora, o ARC é shiny e não há nenhuma razão para evitá-lo (desde que você possa lidar com as restrições de versão do sistema operacional). Para código não-ARC, você pode passar -fno-objc-arc em uma base arquivo-a-arquivo. O Xcode infelizmente torna isso muito mais difícil do que deveria ser na prática. Você provavelmente deve mover o código não-ARC para um xcodeproj separado para simplificar isso.

Em conclusão, mude para o ARC assim que puder e nunca olhe para trás.


EDITAR

Eu vi alguns comentários ao longo das linhas de “usar ARC não é um substituto para conhecer as regras de gerenciamento de memory Cocoa”. Isso é verdade, mas é importante entender por que e por que não. Primeiro, se todo o seu código usa ARC, e você viola as Três Palavras Mágicas por todo o lugar, você ainda não terá problemas. Chocante dizer, mas lá vai você. A ARC pode reter algumas coisas que você não quis manter, mas também as liberará, então isso nunca importará. Se eu estivesse ensinando uma nova class em Cocoa hoje, provavelmente gastaria no máximo cinco minutos com as regras reais de gerenciamento de memory, e provavelmente mencionaria apenas as regras de nomeação de gerenciamento de memory ao discutir a nomenclatura KVC. Com o ARC, acredito que você poderia realmente se tornar um programador iniciante decente sem aprender as regras de gerenciamento de memory.

Mas você não poderia se tornar um programador intermediário decente. Você precisa conhecer as regras para fazer a ponte corretamente com o Core Foundation, e todo programador intermediário precisa lidar com o CF em algum momento. E você precisa conhecer as regras para o código ARC / MRC misto. E você precisa conhecer as regras quando começar a brincar com os pointers void* para o id (que você continua a precisar executar corretamente o KVO). E blocos … bem, o gerenciamento de memory de bloco é simplesmente estranho.

Então, meu ponto é que o gerenciamento de memory subjacente ainda é importante, mas onde eu costumava passar um tempo significativo informando e reafirmando as regras para novos programadores, com o ARC ele está se tornando um tópico mais avançado. Eu prefiro fazer com que os novos desenvolvedores pensem em termos de charts de objects, em vez de preencher suas cabeças com as chamadas subjacentes para objc_retain() .

Respostas melhores e mais técnicas do que as minhas, mas aqui vai:

  • ARC! = Coleta de lixo. Não há penalidade de tempo de execução, isso é feito em tempo de compilation.
  • ARC também! = Apenas liberando tudo automaticamente, como você sugere no seu comentário. Leia os documentos
  • É incrível quando você percebe o quanto de gerenciamento de referência manual você estava fazendo
  • Use-o!
  • Uma desvantagem – manter o código antigo, sem arco voltaico, torna-se subitamente muito tedioso.

Quanto benefício a ARC pode trazer para um projeto?

O benefício é um grau significativo de proteção contra erros comuns de gerenciamento de memory. Vazamentos causados ​​por falha ao liberar um object e falhas devido à falha em reter ou liberar prematuramente um object devem ser significativamente reduzidos. Você ainda precisa entender o modelo de memory contada de referência para poder classificar suas referências como fortes ou fracas, evitar reter ciclos e assim por diante.

Quanto a garbage collection realmente ‘custa’?

Não há garbage collection no iOS. O ARC é semelhante ao GC, pois você não precisa reter ou liberar objects manualmente. É diferente do GC em que não há coletor de lixo. O modelo de retenção / liberação ainda se aplica, é apenas que o compilador insere as chamadas de gerenciamento de memory apropriadas em seu código para você em tempo de compilation.

Você tem usado o ARC e, em caso afirmativo, como você o encontrou até agora?

É um pouco desconcertante se você está acostumado a referenciar a contagem, mas isso é apenas uma questão de se acostumar com isso e aprender a confiar que o compilador realmente fará a coisa certa. Parece uma continuação da mudança para propriedades que veio com o Objective-C 2.0, que foi outro grande passo para simplificar o gerenciamento de memory. Sem as chamadas de gerenciamento de memory manual, seu código fica um pouco mais curto e mais fácil de ler.

O único problema com o ARC é que ele não é suportado em versões mais antigas do iOS, então você precisa levar isso em conta antes de decidir adotá-lo.

Eu acho que o ARC é uma ótima ideia. Comparado ao GC, você pode ter seu bolo e comê-lo também. Costumo acreditar que a MRC impõe uma “disciplina” inestimável para o gerenciamento de memory que todos se beneficiariam. Mas também concordo que a verdadeira questão a ter em conta é a Propriedade do Objeto e os Gráficos de Objetos (como muitos apontaram), e não as contagens de referência de baixo nível em si.

Para concluir: ARC não é um passe livre para ser insensato sobre a memory; é uma ferramenta para ajudar os humanos a evitar tarefas repetitivas, que causam estresse e são propensos a erros, portanto melhor delegates a uma máquina (o compilador, neste caso).

Dito isso, eu sou pessoalmente um artesão e ainda não fiz a transição. Eu comecei a usar o Git …

ATUALIZAÇÃO: Então eu migrei todo o meu jogo, incluindo a biblioteca gl, e sem problemas até agora (exceto com o assistente de migration no Xcode 4.2). Se você está começando um novo projeto, vá em frente.

Eu usei isso em alguns projetos (reconhecidamente pequenos), e eu tenho apenas boas experiências, tanto em desempenho quanto em confiabilidade.

Uma pequena nota de caucanvas é que você precisa aprender a fazer: s e não: s de referências fracas para não causar loops de referência se você estiver codificando sua UI por conta própria, o designer tende a fazer um bom trabalho automaticamente se você configurar sua GUI usando-a.

A única desvantagem que encontrei é se você usa uma biblioteca com muitas funções e dados do CoreFoundation. No MRC você não precisa se preocupar em usar um CFStringRef vez de um NSString* . No ARC, você tem que especificar como os dois interagem (ponte básica? Solte o object CoreFoundation e mova-o para ARC? Faça um object Cocoa como um object retido +1 CoreFoundation?) Além disso, no OS X, ele só está disponível em 64- código de bit (embora eu tenha um header que funcione em torno disso …).