Respostas:
Há algumas coisas que comecei a fazer que não considero padrão:
1) Com o advento das propriedades, não uso mais "_" para prefixar variáveis de classe "privadas". Afinal, se uma variável pode ser acessada por outras classes, não deveria haver uma propriedade para ela? Eu sempre não gostei do prefixo "_" para tornar o código mais feio e agora posso deixá-lo de fora.
2) Falando em assuntos particulares, prefiro colocar definições de métodos particulares no arquivo .m em uma extensão de classe como:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
Por que bagunçar o arquivo .h com coisas que as pessoas de fora não deveriam se importar? O empty () funciona para categorias privadas no arquivo .m e emite avisos de compilação se você não implementar os métodos declarados.
3) Decidi colocar dealloc na parte superior do arquivo .m, logo abaixo das diretivas @synthesize. O que você desaloca não deveria estar no topo da lista de coisas que deseja pensar em uma classe? Isso é especialmente verdade em um ambiente como o iPhone.
3.5) Nas células da tabela, torne cada elemento (incluindo a própria célula) opaco para o desempenho. Isso significa definir a cor de fundo apropriada em tudo.
3.6) Ao usar um NSURLConnection, como regra, você pode implementar o método delegate:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
Acho que a maioria das chamadas na web é muito singular e é mais uma exceção do que a regra em que você deseja respostas em cache, especialmente para chamadas de serviço da web. A implementação do método conforme mostrado desativa o armazenamento em cache de respostas.
Também interessam algumas boas dicas específicas de Joseph Mattiello sobre o iPhone (recebidas em uma lista de discussão do iPhone). Há mais, mas essas foram as mais úteis que pensei (note que agora alguns bits foram ligeiramente editados a partir do original para incluir detalhes oferecidos nas respostas):
4) Use apenas precisão dupla se for necessário, como ao trabalhar com o CoreLocation. Certifique-se de terminar suas constantes em 'f' para que o gcc as armazene como flutuadores.
float val = someFloat * 2.2f;
Isso é importante principalmente quando someFloat
na verdade, pode ser um duplo, você não precisa da matemática de modo misto, pois está perdendo a precisão em 'val' no armazenamento. Embora os números de ponto flutuante sejam suportados no hardware dos iPhones, ainda pode levar mais tempo para fazer aritmética de precisão dupla em oposição à precisão única. Referências:
Nos telefones mais antigos, supostamente os cálculos operam na mesma velocidade, mas você pode ter mais componentes de precisão únicos nos registros do que o dobro, portanto, para muitos cálculos, a precisão única acaba sendo mais rápida.
5) Defina suas propriedades como nonatomic
. Eles estãoatomic
por padrão e, após a síntese, o código do semáforo será criado para evitar problemas de multiencadeamento. 99% de vocês provavelmente não precisam se preocupar com isso, e o código é muito menos inchado e mais eficiente em termos de memória quando definido como não-atômico.
6) O SQLite pode ser uma maneira muito, muito rápida de armazenar em cache grandes conjuntos de dados. Um aplicativo de mapa, por exemplo, pode armazenar em cache seus blocos em arquivos SQLite. A parte mais cara é a E / S do disco. Evite muitas gravações pequenas enviando BEGIN;
eCOMMIT;
entre blocos grandes. Utilizamos um timer de 2 segundos, por exemplo, que é redefinido a cada novo envio. Quando expira, enviamos COMMIT; , o que faz com que todas as suas gravações ocorram em um grande bloco. O SQLite armazena dados de transação em disco e, ao fazer isso, o agrupamento Begin / End evita a criação de muitos arquivos de transação, agrupando todas as transações em um arquivo.
Além disso, o SQL bloqueará sua GUI se estiver no seu thread principal. Se você tiver uma consulta muito longa, é uma boa ideia armazenar suas consultas como objetos estáticos e executar seu SQL em um thread separado. Certifique-se de agrupar qualquer coisa que modifique o banco de dados para cadeias de caracteres de consulta em @synchronize() {}
blocos. Para consultas curtas, basta deixar as coisas no segmento principal para facilitar a conveniência.
Mais dicas de otimização do SQLite estão aqui, embora o documento pareça desatualizado, muitos dos pontos provavelmente ainda são bons;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
Quando métodos ou funções adotam um argumento de sequência de formato, você deve ter controle sobre o conteúdo da sequência de formato.
Por exemplo, ao registrar seqüências de caracteres, é tentador passar a variável de sequência como o único argumento para NSLog
:
NSString *aString = // get a string from somewhere;
NSLog(aString);
O problema é que a cadeia pode conter caracteres que são interpretados como cadeias de formato. Isso pode levar a resultados errados, falhas e problemas de segurança. Em vez disso, você deve substituir a variável string por uma string formatada:
NSLog(@"%@", aString);
Use convenções e terminologia padrão de nomenclatura e formatação do cacau, em vez do que você estiver acostumado a partir de outro ambiente. Não são muitos desenvolvedores de cacau lá fora, e quando mais um deles começa a trabalhar com o seu código, que vai ser muito mais acessível se olha e se sente semelhante a outro código de cacau.
Exemplos do que fazer e do que não fazer:
id m_something;
na interface de um objeto e chame-o de variável ou campo membro ; use something
ou _something
como nome e chame-a de variável de instância .-getSomething
; o nome apropriado de cacau é justo -something
.-something:
; deveria ser-setSomething:
-[NSObject performSelector:withObject:]
, não NSObject::performSelector
.O que quer que você faça, não use a notação húngara no estilo Win16 / Win32. Até a Microsoft desistiu disso com a mudança para a plataforma .NET.
Historicamente, o gerenciamento de memória das tomadas tem sido ruim. A melhor prática atual é declarar pontos de venda como propriedades:
@interface MyClass :NSObject {
NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end
O uso de propriedades torna clara a semântica do gerenciamento de memória; Ele também fornece um padrão consistente se você usar a síntese de variáveis de instância.
NOTA: No Xcode 4, isso agora está incorporado ao IDE.
Você usa o Clang Static Analyzer para - sem surpresa - analisar seu código C e Objective-C (sem C ++ ainda) no Mac OS X 10.5. É trivial instalar e usar:
cd
para o diretório do projeto.scan-build -k -V xcodebuild
.(Existem algumas restrições adicionais, etc., em particular, você deve analisar um projeto em sua configuração "Debug" - consulte http://clang.llvm.org/StaticAnalysisUsage.html para obter detalhes - mas isso é mais ou menos o que se resume.)
O analisador produz um conjunto de páginas da Web para você que mostra o gerenciamento provável da memória e outros problemas básicos que o compilador não consegue detectar.
Este é sutil, mas prático. Se você estiver se passando como delegado para outro objeto, redefina o delegado desse objeto antes de você dealloc
.
- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}
Ao fazer isso, você garante que não serão enviados mais métodos delegados. Enquanto você está prestes a dealloc
desaparecer no éter, deseja ter certeza de que nada poderá lhe enviar mais mensagens por acidente. Lembre-se self.someObject pode ser retido por outro objeto (pode ser um singleton ou no pool de liberação automática ou o que for) e até você dizer "pare de me enviar mensagens!", Ele acha que seu objeto está prestes a ser desalocado é um jogo justo.
Entrar nesse hábito irá salvá-lo de muitas falhas estranhas que são difíceis de depurar.
O mesmo princípio se aplica à Observação do valor-chave e às NSNotifications também.
Editar:
Ainda mais defensivo, mude:
self.someObject.delegate = NULL;
para dentro:
if (self.someObject.delegate == self)
self.someObject.delegate = NULL;
Memory Management Programming Guide for Cocoa
: Additional cases of weak references in Cocoa include, but are not restricted to, table data sources, outline view items, notification observers, and miscellaneous targets and delegates. In most cases, the weak-referenced object is aware of the other object’s weak reference to it, as is the case for circular references, and is responsible for notifying the other object when it deallocates.
nil == NULL
. Eles são exatamente os mesmos, exceto que nil
é um id
e NULL
é um void *
. Sua afirmação não é verdadeira.
@kendell
Ao invés de:
@interface MyClass (private)
- (void) someMethod
- (void) someOtherMethod
@end
Usar:
@interface MyClass ()
- (void) someMethod
- (void) someOtherMethod
@end
Novo no Objective-C 2.0.
As extensões de classe são descritas na Referência do Objective-C 2.0 da Apple.
"As extensões de classe permitem que você declare API adicional necessária para uma classe em locais diferentes do bloco @interface da classe principal"
Portanto, eles fazem parte da classe real - e NÃO de uma categoria (privada) além da classe. Diferença sutil, mas importante.
()
vez de (Private)
(ou algum outro nome de categoria): Você pode redefinir as propriedades como readwrite enquanto para o público elas são apenas de leitura. :)
Como você (1) normalmente não tem controle direto sobre sua vida útil, os objetos liberados automaticamente podem persistir por um período comparativamente longo e aumentar desnecessariamente a área de armazenamento de memória do seu aplicativo. Enquanto na área de trabalho, isso pode ter pouca importância, em plataformas mais restritas, isso pode ser um problema significativo. Em todas as plataformas, portanto, e especialmente em plataformas mais restritas, é considerado uma prática recomendada evitar o uso de métodos que levariam a objetos liberados automaticamente e, em vez disso, é recomendável usar o padrão de alocação / inicialização.
Assim, ao invés de:
aVariable = [AClass convenienceMethod];
onde for possível, você deve usar:
aVariable = [[AClass alloc] init];
// do things with aVariable
[aVariable release];
Ao escrever seus próprios métodos que retornam um objeto recém-criado, você pode tirar proveito da convenção de nomenclatura do Cocoa para sinalizar ao destinatário que ele deve ser liberado, acrescentando o nome do método com "novo".
Assim, em vez de:
- (MyClass *)convenienceMethod {
MyClass *instance = [[[self alloc] init] autorelease];
// configure instance
return instance;
}
você poderia escrever:
- (MyClass *)newInstance {
MyClass *instance = [[self alloc] init];
// configure instance
return instance;
}
Como o nome do método começa com "novo", os consumidores da sua API sabem que são responsáveis por liberar o objeto recebido (consulte, por exemplo, o newObject
método NSObjectController ).
(1) Você pode assumir o controle usando seus próprios pools de autorelease locais. Para mais informações, consulte Pools de liberação automática .
NSAutoreleasePool
. Mas somente depois de confirmar que isso realmente é um problema. Otimização prematura e tudo o que ...
Algumas delas já foram mencionadas, mas aqui está o que consigo pensar:
#pragma mark [section]
. Geralmente, agrupo de acordo com meus próprios métodos, as substituições de cada subclasse e qualquer informação ou protocolo formal. Isso torna muito mais fácil pular exatamente para o que estou procurando. No mesmo tópico, agrupe métodos semelhantes (como os métodos delegados de uma exibição de tabela), não os cole em qualquer lugar.#define
vontade o fará ou armazenar em cache uma matriz em vez de classificá-la sempre que os dados forem necessários. Há muito o que dizer sobre isso, mas o ponto principal é que não escreva código até que você precise, ou o criador de perfil diz para você. Torna as coisas muito mais fáceis de manter a longo prazo.NSLog( @"stub" )
ou, no entanto, deseja acompanhar as coisas.Finish what you start
você também pode usar // TODO:
para marcar o código para conclusão, que será exibido no menu suspenso.
Escreva testes de unidade. Você pode testar muitas coisas no Cocoa que podem ser mais difíceis em outras estruturas. Por exemplo, com o código da interface do usuário, você geralmente pode verificar se as coisas estão conectadas como deveriam e confiar que elas funcionarão quando usadas. E você pode configurar o estado e chamar métodos delegados facilmente para testá-los.
Você também não tem visibilidade de método público x protegido x privado, impedindo a criação de testes para seus internos.
Regra de Ouro: Se você, alloc
então você release
!
ATUALIZAÇÃO: A menos que você esteja usando o ARC
copy
, mutableCopy
, new
ou retain
.
Não escreva Objective-C como se fosse Java / C # / C ++ / etc.
Uma vez vi uma equipe acostumada a escrever aplicativos da Web Java EE tentando escrever um aplicativo de desktop Cocoa. Como se fosse um aplicativo da web Java EE. Havia muito AbstractFooFactory e FooFactory e IFoo e Foo voando quando tudo o que eles realmente precisavam era de uma classe Foo e possivelmente um protocolo Fooable.
Parte de garantir que você não faça isso é realmente entender as diferenças no idioma. Por exemplo, você não precisa das classes abstract factory e factory acima, porque os métodos da classe Objective-C são despachados tão dinamicamente quanto os métodos de instância e podem ser substituídos nas subclasses.
Certifique-se de marcar a página Magia de depuração . Esta deve ser sua primeira parada ao bater a cabeça contra uma parede enquanto tenta encontrar a fonte de um inseto de cacau.
Por exemplo, ele mostrará como encontrar o método em que você alocou a memória pela primeira vez que mais tarde está causando falhas (como durante o encerramento do aplicativo).
Tente evitar o que agora decidi chamar de Newbiecategoryaholism. Quando os recém-chegados ao Objective-C descobrem categorias, geralmente ficam loucos, adicionando pequenas categorias úteis a todas as classes existentes ( "O quê? Posso adicionar um método para converter um número em números romanos em NSNumber rock on!" ).
Não faça isso.
Seu código será mais portátil e mais fácil de entender, com dezenas de pequenos métodos de categoria espalhados por duas dúzias de classes de fundação.
Na maioria das vezes, quando você realmente pensa que precisa de um método de categoria para ajudar a simplificar algum código, verá que nunca acaba reutilizando o método.
Existem outros perigos também, a menos que você esteja colocando o nome dos métodos de categoria (e quem além do ddribin totalmente insano é?), Há uma chance de que a Apple, ou um plug-in ou outra coisa em execução no seu espaço de endereço também defina a mesma categoria método com o mesmo nome com um efeito colateral ligeiramente diferente ....
ESTÁ BEM. Agora que você foi avisado, ignore o "não faça esta parte". Mas exerça extrema restrição.
Resista a subclassificar o mundo. No Cocoa, muito é feito através da delegação e uso do tempo de execução subjacente, que em outras estruturas é feito através da subclassificação.
Por exemplo, em Java, você usa muito instâncias de *Listener
subclasses anônimas e, no .NET, usa muito suas EventArgs
subclasses. No cacau, você também não faz - a ação-alvo é usada.
Ao classificar seqüências de caracteres para apresentar ao usuário, você não deve usar o compare:
método simples . Em vez disso, você sempre deve usar métodos de comparação localizados como localizedCompare:
ou localizedCaseInsensitiveCompare:
.
Para obter mais detalhes, consulte Pesquisando, comparando e classificando cadeias .
Você normalmente deve usar o recurso Propriedades declaradas do Objective-C 2.0 para todas as suas propriedades. Se eles não forem públicos, adicione-os em uma extensão de classe. O uso de propriedades declaradas torna a semântica de gerenciamento de memória imediatamente clara e facilita a verificação de seu método de desdobramento - se você agrupar suas declarações de propriedades, poderá digitalizá-las rapidamente e comparar com a implementação do seu método de desdobramento.
Você deve pensar bastante antes de não marcar as propriedades como 'não atômicas'. Como observa o Guia de Linguagem de Programação do Objective C , as propriedades são atômicas por padrão e incorrem em custos consideráveis. Além disso, simplesmente tornar todas as suas propriedades atômicas não torna seu aplicativo seguro para threads. Observe também, é claro, que se você não especificar 'não-atômico' e implementar seus próprios métodos de acesso (em vez de sintetizá-los), deverá implementá-los de maneira atômica.
Como observa essa pergunta , as mensagens para nil
são válidas no Objective-C. Embora isso freqüentemente seja uma vantagem - levando a um código mais limpo e mais natural -, o recurso pode ocasionalmente levar a erros peculiares e difíceis de rastrear se você obtiver um nil
valor quando não o esperava.
Use NSAssert e amigos. Eu uso nulo como objeto válido o tempo todo ... especialmente o envio de mensagens para nil é perfeitamente válido no Obj-C. No entanto, se eu realmente quiser ter certeza do estado de uma variável, eu uso o NSAssert e o NSParameterAssert, o que ajuda a rastrear os problemas facilmente.
Simples, mas muitas vezes esquecido. De acordo com as especificações:
Em geral, métodos em diferentes classes que possuem o mesmo seletor (o mesmo nome) também devem compartilhar os mesmos tipos de retorno e argumento. Essa restrição é imposta pelo compilador para permitir a ligação dinâmica.
nesse caso, todos os mesmos seletores nomeados, mesmo que em classes diferentes , serão considerados como tendo tipos idênticos de retorno / argumento. Aqui está um exemplo simples.
@interface FooInt:NSObject{}
-(int) print;
@end
@implementation FooInt
-(int) print{
return 5;
}
@end
@interface FooFloat:NSObject{}
-(float) print;
@end
@implementation FooFloat
-(float) print{
return 3.3;
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
id f1=[[FooFloat alloc]init];
//prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
NSLog(@"%f",[f1 print]);
FooFloat* f2=[[FooFloat alloc]init];
//prints 3.3 expectedly as the static type is FooFloat
NSLog(@"%f",[f2 print]);
[f1 release];
[f2 release]
[pool drain];
return 0;
}
Se você estiver usando o Leopard (Mac OS X 10.5) ou posterior, poderá usar o aplicativo Instruments para encontrar e rastrear vazamentos de memória. Após criar seu programa no Xcode, selecione Executar> Iniciar com a Ferramenta de Desempenho> Vazamentos.
Mesmo que seu aplicativo não mostre vazamentos, você pode manter objetos por muito tempo. Em Instrumentos, você pode usar o instrumento ObjectAlloc para isso. Selecione o instrumento ObjectAlloc no documento Instruments e exiba os detalhes do instrumento (se ele ainda não estiver aparecendo) escolhendo Exibir> Detalhes (ele deve ter uma marca de seleção ao lado). Em "Tempo de vida da alocação" nos detalhes do ObjectAlloc, escolha o botão de opção ao lado de "Criado e ainda vivo".
Agora, sempre que você parar de gravar seu aplicativo, selecionar a ferramenta ObjectAlloc mostrará quantas referências existem para cada objeto ainda vivo no seu aplicativo na coluna "# Net". Certifique-se de não apenas olhar para suas próprias classes, mas também para as classes dos objetos de nível superior dos arquivos NIB. Por exemplo, se você não possui janelas na tela e vê referências a um NSWindow ainda vivo, talvez não o tenha lançado no seu código.
Limpar em desalocação.
Esta é uma das coisas mais fáceis de esquecer - esp. ao codificar a 150 mph. Sempre, sempre, sempre limpe seus atributos / variáveis de membro em desalocação.
Eu gosto de usar os atributos do Objc 2 - com a nova notação de pontos -, portanto, isso torna a limpeza indolor. Muitas vezes, tão simples quanto:
- (void)dealloc
{
self.someAttribute = NULL;
[super dealloc];
}
Isso cuidará da liberação para você e definirá o atributo como NULL (que considero programação defensiva - caso outro método mais abaixo no desalocamento acesse a variável membro novamente - raro, mas pode acontecer).
Com o GC ativado na 10.5, isso não é mais necessário - mas você ainda pode precisar limpar os outros recursos que criar, pode fazer isso no método finalize.
-init
e -dealloc
métodos podem ser encontrados aqui: mikeash.com/?page=pyblog/...
Todos esses comentários são ótimos, mas estou realmente surpreso que ninguém tenha mencionado o Guia de estilo Objective-C do Google, publicado há algum tempo. Eu acho que eles fizeram um trabalho muito completo.
Além disso, tópico semi-relacionado (com espaço para mais respostas!):
Quais são as pequenas dicas e truques do Xcode que você gostaria de conhecer há 2 anos? .
Um exemplo bastante óbvio para um iniciante: use o recurso de indentação automática do Xcode para o seu código. Mesmo se você estiver copiando / colando de outra fonte, depois de colar o código, você pode selecionar todo o bloco de código, clicar com o botão direito do mouse e escolher a opção de re-recuar tudo dentro desse bloco.
O Xcode realmente analisará essa seção e a indentará com base em colchetes, loops etc. É muito mais eficiente do que pressionar a barra de espaço ou a tecla Tab para cada linha.
Eu sei que ignorei isso quando comecei a programação de cacau.
Certifique-se de entender as responsabilidades de gerenciamento de memória em relação aos arquivos NIB. Você é responsável por liberar os objetos de nível superior em qualquer arquivo NIB carregado. Leia a documentação da Apple sobre o assunto.
Ative todos os avisos do GCC e depois os que são causados regularmente pelos cabeçalhos da Apple para reduzir o ruído.
Também execute a análise estática de Clang com frequência; você pode habilitá-lo para todas as compilações através da configuração de compilação "Executar Static Analyzer".
Escreva testes de unidade e execute-os com cada compilação.
Variáveis e propriedades
1 / Mantendo seus cabeçalhos limpos, ocultando a implementação
Não inclua variáveis de instância em seu cabeçalho. Variáveis privadas colocadas na continuação de classe como propriedades. Variáveis públicas são declaradas como propriedades públicas no seu cabeçalho. Se for apenas para leitura, declare-o como somente leitura e substitua-o como readwrite na continuação da classe. Basicamente, não estou usando variáveis, apenas propriedades.
2 / Dê um nome de variável não padrão às suas propriedades, por exemplo:
@synthesize property = property_;
Razão 1: você detectará erros causados pelo esquecimento do "eu". ao atribuir a propriedade. Razão 2: Nas minhas experiências, o Leak Analyzer in Instruments tem problemas para detectar vazamentos de propriedades com o nome padrão.
3 / Nunca use reter ou liberar diretamente nas propriedades (ou apenas em situações muito excepcionais). Em seu negócio, apenas atribua um valor nulo. As propriedades de retenção destinam-se a lidar com a retenção / liberação por si próprias. Você nunca sabe se um levantador não está, por exemplo, adicionando ou removendo observadores. Você deve usar a variável diretamente apenas dentro do seu setter e getter.
Visualizações
1 / Coloque todas as definições de exibição em um xib, se puder (a exceção geralmente é conteúdo dinâmico e configurações de camada). Economiza tempo (é mais fácil do que escrever código), é fácil mudar e mantém seu código limpo.
2 / Não tente otimizar visualizações diminuindo o número de visualizações. Não crie UIImageView no seu código, em vez de xib, apenas porque você deseja adicionar subviews a ele. Use UIImageView como plano de fundo. A estrutura de exibição pode lidar com centenas de visualizações sem problemas.
3 / IBOutlets nem sempre precisam ser mantidos (ou fortes). Observe que a maioria dos seus IBOutlets faz parte da hierarquia de visualizações e, portanto, é retida implicitamente.
4 / Libere todos os IBOutlets no viewDidUnload
5 / Ligue para viewDidUnload do seu método de desdobramento. Não é chamado implicitamente.
Memória
1 / Liberar objetos automaticamente quando você os cria. Muitos bugs são causados ao mover sua chamada de liberação para uma ramificação if-else ou após uma declaração de retorno. A liberação em vez da liberação automática deve ser usada apenas em situações excepcionais - por exemplo, quando você está esperando por um runloop e não deseja que seu objeto seja liberado automaticamente muito cedo.
2 / Mesmo se você estiver usando a Contagem de referência automática, você precisa entender perfeitamente como os métodos de liberação de retenção funcionam. O uso da liberação manual de retenção não é mais complicado do que o ARC, em ambos os casos você deve considerar vazamentos e ciclos de retenção. Considere usar a liberação de retenção manualmente em grandes projetos ou hierarquias de objetos complicadas.
Comentários
1 / Crie seu código documentado automaticamente. Todo nome de variável e método deve dizer o que está fazendo. Se o código for escrito corretamente (você precisará de muita prática nisso), não precisará de nenhum comentário de código (não o mesmo que comentários de documentação). Os algoritmos podem ser complicados, mas o código deve ser sempre simples.
2 / Às vezes, você precisa de um comentário. Geralmente para descrever um comportamento ou hack de código não aparente. Se você acha que precisa escrever um comentário, primeiro tente reescrever o código para ser mais simples e sem a necessidade de comentários.
Indentação
1 / Não aumente muito o recuo. A maior parte do código do método deve ser recuada no nível do método. Blocos aninhados (se, para etc.) diminuem a legibilidade. Se você tiver três blocos aninhados, tente colocar os blocos internos em um método separado. Quatro ou mais blocos aninhados nunca devem ser usados. Se a maior parte do código do método estiver dentro de um if, negue a condição if, exemplo:
if (self) {
//... long initialization code ...
}
return self;
if (!self) {
return nil;
}
//... long initialization code ...
return self;
Entenda o código C, principalmente estruturas C
Observe que o Obj-C é apenas uma camada OOP leve sobre a linguagem C. Você deve entender como as estruturas básicas de código em C funcionam (enumerações, estruturas, matrizes, ponteiros etc.). Exemplo:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);
é o mesmo que:
CGRect frame = view.frame;
frame.size.height += 20;
view.frame = frame;
E muitos mais
Mantenha seu próprio documento de padrões de codificação e atualize-o com frequência. Tente aprender com seus erros. Entenda por que um bug foi criado e tente evitá-lo usando padrões de codificação.
Atualmente, nossos padrões de codificação têm cerca de 20 páginas, uma mistura de padrões de codificação Java, padrões Obj-C / C ++ do Google e nossos próprios complementos. Documente seu código, use recuo padrão padrão, espaços em branco e linhas em branco nos lugares certos etc.
Seja mais funcional .
O Objective-C é uma linguagem orientada a objetos, mas a estrutura do Cocoa reconhece o estilo funcional e é projetada em muitos casos.
Há separação de mutabilidade. Use classes imutáveis como objeto primário e mutável como secundário. Por exemplo, use o NSArray principalmente e use o NSMutableArray somente quando necessário.
Existem funções puras. Não muitos, compre muitas APIs de estrutura projetadas como função pura. Veja funções como CGRectMake()
ou CGAffineTransformMake()
. Obviamente, a forma do ponteiro parece mais eficiente. No entanto, argumentos indiretos com ponteiros não podem oferecer efeitos colaterais. Projete estruturas o máximo possível. Separe objetos de estado pares. Use em -copy
vez de -retain
passar um valor para outro objeto. Porque o estado compartilhado pode influenciar a mutação no valor em outro objeto silenciosamente. Portanto, não pode ser livre de efeitos colaterais. Se você tiver um valor de externo a partir do objeto, copie-o. Portanto, também é importante projetar o estado compartilhado o mínimo possível.
No entanto, não tenha medo de usar funções impuras também.
Há uma avaliação preguiçosa. Veja algo como -[UIViewController view]
propriedade. A vista não será criada quando o objeto for criado. Ele será criado quando o chamador ler a view
propriedade pela primeira vez. UIImage
não será carregado até ser realmente desenhado. Existem muitas implementações como este design. Esse tipo de design é muito útil para o gerenciamento de recursos, mas se você não conhece o conceito de avaliação lenta, não é fácil entender o comportamento deles.
Há fechamento. Use blocos C, tanto quanto possível. Isso simplificará muito sua vida. Mas leia mais uma vez sobre o gerenciamento de memória de bloco antes de usá-lo.
Há GC semi-automático. NSAutoreleasePool. Use -autorelease
primário. Use o manual -retain/-release
secundário quando realmente precisar. (ex: otimização de memória, exclusão explícita de recursos)
autorelease
que manterá a memória por mais tempo em geral, e o manual retain/release
pode reduzir o consumo de memória no caso. No entanto, deve ser uma orientação para otimização de caso especial (mesmo que você esteja se sentindo sempre!), Não pode ser o motivo para generalizar a otimização prematura como prática . E, de fato, sua sugestão não é oposta a mim. Eu mencionei-lo como caso de realmente necessidade :)