The Objective-C Style Guide utilizado por Fábio Nogueira
- Linguagem
- Quando utilizar ponto
- Organização de código
- Espaços
- Padrão para declarações
- Nomenclatura
- Métodos
- Variáveis
- Propriedades
- Sintaxe Dot-Notation
- Literais
- Tipos enumerados
- Sintaxe Case
- Booleanos
- Métodos inicializadores
- Métodos Construtores de classes
- Funções CGRect
- Singletons
- TableView
O Inglês deve ser utilizado. Português será aceito apenas para dados de modelo.
Utilize o ponto sempre quando for acessar e alterar uma propriedade. Em todos os outros casos é recomendo a utilização dos colchetes.
Exemplo correto:
view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate;
Inadequado:
[view setBackgroundColor:[UIColor orangeColor]];
UIApplication.sharedApplication.delegate;
Use #pragma mark -
para organizar as propriedades e métodos por categorias.
#pragma mark - Lifecycle
- (instancetype)init {}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}
#pragma mark - Custom Accessors
- (void)setCustomProperty:(id)value {}
- (id)customProperty {}
#pragma mark - IBActions
- (IBAction)submitData:(id)sender {}
#pragma mark - Public
- (void)publicMethod {}
#pragma mark - Private
- (void)privateMethod {}
#pragma mark - Protocol conformance
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone {}
#pragma mark - NSObject
- (NSString *)description {}
- Utilizar indentação com 4 espaços. Nunca utilizar tabs para indentação. Altere a propriedade do Xcode para alterar o tab por 4 espaços.
- Chaves de métodos (
if
/else
/switch
/while
, etc) sempre será aberta na mesma linha e fechadas em uma nova linha.
Exemplo correto:
if (user.isHappy) {
//Do something
} else {
//Do something else
}
Inadequado:
if (user.isHappy)
{
//Do something
}
else {
//Do something else
}
- Não utilizar a formatação default do Xcode para métodos com chamadas parecidas com o exemplo abaixo.
Exemplo correto:
// blocks are easily readable
[UIView animateWithDuration:1.0 animations:^{
// something
} completion:^(BOOL finished) {
// something
}];
Inadequado:
// colon-aligning makes the block indentation hard to read
[UIView animateWithDuration:1.0
animations:^{
// something
}
completion:^(BOOL finished) {
// something
}];
- Não deverá ter linha vazia acima das declarações condicionais
- (void)methodA {
BOOL varA = YES;
if (varA) {
}
}
- Exemplos de declaração quando utilizado Arrays e Dictionarys
[mapping addAttributeMappingsFromArray:@[
@"codigo",
@"nome",
@"idade",
@"profissao",
@"religiao",
@"recomendacao"]
];
Convenção de nomes da Apple devem ser respeitadas sempre que possível, especialmente aqueles relacionados com as regras de gerênciamento de memória (NARC).
- Nomes de propriedades e métodos longos, descritivos são bem aceitos. Métodos podem ser escritos parecendo verdadeiras frases de objetivos.
Exemplo correto:
UIButton *settingsButton;
Inadequado:
UIButton *setBut;
- Constantes devem conter um espaço após o * da atribuição.
Exemplo correto:
const CGFloat * components = CGColorGetComponents(color.CGColor);
- Constantes devem ser camel-case com todas as palavras e prefixos relacionados a classe e depois seu objetivo.
Exemplo correto:
static NSTimeInterval const RWTTutorialViewControllerNavigationFadeAnimationDuration = 0.3;
Inadequado:
static NSTimeInterval const fadetime = 1.7;
- Propriedades devem ser camel-case e começando com a primeira letra minúscula.
Exemplo correto:
@property (strong, nonatomic) NSString *descriptiveVariableName;
As propriedades devem ser chamadas utiizando o self.
. Apenas não há necessidade quando a propriedades for uma criada localmente em algum método.
Váriavéis locais não devem conter self.
- Em assinaturas de método, deve haver um espaço após o tipo de método (- / + símbolo).
- Deve haver um espaço entre os segmentos de método.
- Sempre incluir uma palavra-chave e ser descritivo com a palavra antes do argumento que descreve o argumento.
- Não utilização da palavra "and" para relacionar outro parâmetro de um método
Exemplo correto:
- (void)setExampleText:(NSString *)text image:(UIImage *)image;
- (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag;
- (id)viewWithTag:(NSInteger)tag;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
Inadequado:
-(void)setT:(NSString *)text i:(UIImage *)image;
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
- (id)taggedView:(NSInteger)tag;
- (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;
- (instancetype)initWith:(int)width and:(int)height; // Never do this.
Métodos privados devem possui o préfixo _
antes do nome
- (void)_privateMethod {}
Exemplo correto:
@interface RWTTutorial : NSObject
@property (strong, nonatomic) NSString *tutorialName;
@end
Inadequado:
@interface RWTTutorial : NSObject {
NSString *tutorialName;
}
Atributos de propriedade deve ser explicitamente listados, e vai ajudar novos programadores ao ler o código. A ordem de propriedades deve ser de armazenamento, em seguida, atomicidade, o que é consistente com o código gerado automaticamente ao conectar elementos da interface de Interface Builder.
Exemplo correto:
@property (weak, nonatomic) IBOutlet UIView *containerView;
@property (strong, nonatomic) NSString *tutorialName;
Inadequado:
@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic) NSString *tutorialName;
Propriedades com valores mutáveis (por exemplo NSString) deve preferir copy
em vez de strong
.
Por quê? Mesmo se você declarou uma propriedade como NSString
alguém pode passar em uma instância de um NSMutableString
e, em seguida, alterá-lo sem você perceber isso.
Exemplo correto:
@property (copy, nonatomic) NSString *tutorialName;
Inadequado:
@property (strong, nonatomic) NSString *tutorialName;
Use Dot syntax apenas para acessar propriedades e não realizar chamadas de métodos. Leia mais aqui
Exemplo correto:
NSInteger arrayCount = [self.array count];
view.backgroundColor = [UIColor orangeColor];
Inadequado:
NSInteger arrayCount = self.array.count;
[view setBackgroundColor:[UIColor orangeColor]];
NSString
, NSDictionary
, NSArray
, e NSNumber
devem ser utilizados de forma literal.
Exemplo correto:
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingStreetNumber = @10018;
Inadequado:
NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];
NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];
NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];
NSNumber *buildingStreetNumber = [NSNumber numberWithInteger:10018];
Constantes são preferidos sobre in-line strings literais ou números, já que permitem a fácil reprodução de variáveis comumente usadas e podem ser rapidamente alterados sem a necessidade de localizar e substituir. Constantes devem ser declarados como constantes static
e não # define
s a menos que explicitamente sendo usado como uma macro.
Exemplo correto:
static NSString * const RWTAboutViewControllerCompanyName = @"RayWenderlich.com";
static CGFloat const RWTImageThumbnailHeight = 50.0;
Inadequado:
#define CompanyName @"RayWenderlich.com"
#define thumbnailHeight 2
Ao usar enums, recomenda-se a usar a nova especificação do tipo fixo subjacente porque tem forte verificação de tipo e conclusão de código. O SDK inclui agora uma macro para facilitar e incentivar a utilização de tipos subjacentes fixos: NS_ENUM ()
For Example:
typedef NS_ENUM(NSInteger, RWTLeftMenuTopItemType) {
RWTLeftMenuTopItemMain,
RWTLeftMenuTopItemShows,
RWTLeftMenuTopItemSchedule
};
Você também pode fazer atribuições de valores explícitos
typedef NS_ENUM(NSInteger, RWTGlobalConstants) {
RWTPinSizeMin = 1,
RWTPinSizeMax = 5,
RWTPinCountMin = 100,
RWTPinCountMax = 500,
};
Inadequado:
enum GlobalConstants {
kMaxPinSize = 5,
kMaxPinCount = 500,
};
Chaves não são necessários para instruções case, a menos imposto pelo compilador. Quando um caso contém mais de uma linha, deve ser adicionado chaves.
switch (condition) {
case 1:
// ...
break;
case 2: {
// ...
// Multi-line example using braces
break;
}
case 3:
// ...
break;
default:
// ...
break;
}
nil
é interpretado como NO
portanto não é necessário compará-lo em condições. Nunca compare algo diretamente com YES
porque YES
é definido como 1 e um BOOL
pode ser de até 8 bits.
Isso permite uma maior consistência entre os arquivos e maior clareza visual.
Exemplo correto:
if (!someObject) {
}
Inadequado:
if (someObject == nil) {
}
Para um BOOL
, temos dois exemplos:
if (isAwesome)
if (![someObject boolValue])
Inadequado:
if (isAwesome == YES) // Nunca faça isso.
if ([someObject boolValue] == NO)
Se o nome de uma propriedade do tipo BOOL
é expresso como um adjetivo, a propriedade pode omitir o prefixo "is", mas deve continuar especificando o nome convencional para o metodo de acesso get
. Exemplo:
@property (assign, getter=isEditable) BOOL editable;
Utilizar convenção padrão da apple para a inicialização e sempre utilizar instancetype ao invés de id
- (instancetype)init {
self = [super init];
if (self) {
// ...
}
return self;
}
Quando são utilizados métodos construtores da classe, estes devem sempre retornar tipo de 'instancetype' e nunca 'id'. Isso garante que o compilador infere corretamente o tipo de resultado.
@interface Airplane
+ (instancetype)airplaneWithType:(RWTAirplaneType)type;
@end
Ao acessar o x
, y
, width
, ouhight
de um CGRect
, sempre use o CGGeometry
functions em vez de acesso direto a struct. A partir da Apple referência CGGeometry
:
Todas as funções descritas nesta referência que ter estruturas de dados CGRect como entradas implicitamente padronizar esses retângulos antes de calcular os seus resultados. Por esta razão, as aplicações devem evitar directamente a leitura e escrita dos dados armazenados na estrutura de dados CGRect. Em vez disso, use as funções descritas aqui para manipular retângulos e para recuperar as suas características.
Exemplo correto:
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);
CGRect frame = CGRectMake(0.0, 0.0, width, height);
Inadequado:
CGRect frame = self.view.frame;
CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
CGRect frame = (CGRect){ .origin = CGPointZero, .size = frame.size };
Singleton objects should use a thread-safe pattern for creating their shared instance.
+ (instancetype)sharedInstance {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Utilizar o próprio nome da classe para definir os identificadores
[tableview registerClass:[MyCell class] forCellReuseIdentifier:NSStringFromClass([MyCell class])];
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([GameCell class]) bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:NSStringFromClass([GameCell class])];
GameCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([GameCell class]) forIndexPath:indexPath];