在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:samlaudev/Objective-C-Coding-Style开源软件地址:https://github.com/samlaudev/Objective-C-Coding-Style开源编程语言:开源软件介绍:raywenderlich.com Objective-C编码规范这篇编码风格指南概括了raywenderlich.com的编码规范,可能有些删减或修改。 介绍我们制定Objective-C编码规范的原因是我们能够在我们的书,教程和初学者工具包的代码保持优雅和一致。即使我们有很多不同的作者来完成不同的书籍。 这里编码规范有可能与你看到的其他Objective-C编码规范不同,因为它主要是为了打印和web的易读性。 关于作者这编码规范的创建是由很多来自raywenderlich.com团队成员在Nicholas Waynik的带领下共同完成的。团队成员有:Soheil Moayedi Azarpour, Ricardo Rendon Cepeda, Tony Dahbura, Colin Eberhardt, Matt Galloway, Greg Heo, Matthijs Hollemans, Christopher LaPollo, Saul Mora, Andy Pereira, Mic Pringle, Pietro Rea, Cesare Rocchi, Marin Todorov, Nicholas Waynik和Ray Wenderlich 我们也非常感谢New York Times 和Robots & Pencils'Objective-C编码规范的作者。这两个编码规范为本指南的创建提供很好的起点。 背景这里有些关于编码风格Apple官方文档,如果有些东西没有提及,可以在以下文档来查找更多细节:
目录
语言应该使用US英语. 应该: UIColor *myColor = [UIColor whiteColor]; 不应该: UIColor *myColour = [UIColor whiteColor];
代码组织在函数分组和protocol/delegate实现中使用 #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/Event Response
- (IBAction)submitData:(id)sender {}
- (void)someButtonDidPressed:(UIButton*)button
#pragma mark - Protocol conformance
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - Public
- (void)publicMethod {}
#pragma mark - Private
- (void)privateMethod {}
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone {}
#pragma mark - NSObject
- (NSString *)description {}
空格
应该: if (user.isHappy) {
//Do something
} else {
//Do something else
} 不应该: if (user.isHappy)
{
//Do something
}
else {
//Do something else
}
应该: // blocks are easily readable
[UIView animateWithDuration:1.0 animations:^{
// something
} completion:^(BOOL finished) {
// something
}]; 不应该: // colon-aligning makes the block indentation hard to read
[UIView animateWithDuration:1.0
animations:^{
// something
}
completion:^(BOOL finished) {
// something
}];
注释当需要注释时,注释应该用来解释这段特殊代码为什么要这样做。任何被使用的注释都必须保持最新或被删除。 一般都避免使用块注释,因为代码尽可能做到自解释,只有当断断续续或几行代码时才需要注释。例外:这不应用在生成文档的注释
命名Apple命名规则尽可能坚持,特别是与这些相关的memory management rules (NARC)。 长的,描述性的方法和变量命名是好的。 应该: UIButton *settingsButton; 不应该: UIButton *setBut; 三个字符前缀应该经常用在类和常量命名,但在Core Data的实体名中应被忽略。对于官方的raywenderlich.com书、初学者工具包或教程,前缀'RWT'应该被使用。 常量应该使用驼峰式命名规则,所有的单词首字母大写和加上与类名有关的前缀。 应该: static NSTimeInterval const RWTTutorialViewControllerNavigationFadeAnimationDuration = 0.3; 不应该: static NSTimeInterval const fadetime = 1.7; 属性也是使用驼峰式,但首单词的首字母小写。对属性使用auto-synthesis,而不是手动编写@ synthesize语句,除非你有一个好的理由。 应该: @property (strong, nonatomic) NSString *descriptiveVariableName; 不应该: id varnm;
下划线当使用属性时,实例变量应该使用 但有一个特例:在初始化方法里,实例变量(例如,_variableName)应该直接被使用来避免getters/setters潜在的副作用。 局部变量不应该包含下划线。
方法在方法签名中,应该在方法类型(-/+ 符号)之后有一个空格。在方法各个段之间应该也有一个空格(符合Apple的风格)。在参数之前应该包含一个具有描述性的关键字来描述参数。 "and"这个词的用法应该保留。它不应该用于多个参数来说明,就像 应该: - (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; 不应该: -(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.
变量变量尽量以描述性的方式来命名。单个字符的变量命名应该尽量避免,除了在 星号表示变量是指针。例如, 私有变量 应该尽可能代替实例变量的使用。尽管使用实例变量是一种有效的方式,但更偏向于使用属性来保持代码一致性。 通过使用'back'属性(_variable,变量名前面有下划线)直接访问实例变量应该尽量避免,除了在初始化方法( 应该: @interface RWTTutorial : NSObject
@property (strong, nonatomic) NSString *tutorialName;
@end 不应该: @interface RWTTutorial : NSObject {
NSString *tutorialName;
}
属性特性所有属性特性应该显式地列出来,有助于新手阅读代码。属性特性的顺序应该是storage、atomicity,与在Interface Builder连接UI元素时自动生成代码一致。 应该: @property (weak, nonatomic) IBOutlet UIView *containerView;
@property (strong, nonatomic) NSString *tutorialName; 不应该: @property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic) NSString *tutorialName; NSString应该使用 为什么?即使你声明一个 应该: @property (copy, nonatomic) NSString *tutorialName; 不应该: @property (strong, nonatomic) NSString *tutorialName;
点符号语法点语法是一种很方便封装访问方法调用的方式。当你使用点语法时,通过使用getter或setter方法,属性仍然被访问或修改。想了解更多,阅读这里 点语法应该总是被用来访问和修改属性,因为它使代码更加简洁。[]符号更偏向于用在其他例子。 应该: NSInteger arrayCount = [self.array count];
view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate; 不应该: NSInteger arrayCount = self.array.count;
[view setBackgroundColor:[UIColor orangeColor]];
UIApplication.sharedApplication.delegate;
字面值
应该: NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingStreetNumber = @10018; 不应该: 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];
常量常量是容易重复被使用和无需通过查找和代替就能快速修改值。常量应该使用 应该: static NSString * const RWTAboutViewControllerCompanyName = @"RayWenderlich.com";
static CGFloat const RWTImageThumbnailHeight = 50.0; 不应该: #define CompanyName @"RayWenderlich.com"
#define thumbnailHeight 2
枚举类型当使用 例如: typedef NS_ENUM(NSInteger, RWTLeftMenuTopItemType) {
RWTLeftMenuTopItemMain,
RWTLeftMenuTopItemShows,
RWTLeftMenuTopItemSchedule
}; 你也可以显式地赋值(展示旧的k-style常量定义): typedef NS_ENUM(NSInteger, RWTGlobalConstants) {
RWTPinSizeMin = 1,
RWTPinSizeMax = 5,
RWTPinCountMin = 100,
RWTPinCountMax = 500,
}; 旧的k-style常量定义应该避免除非编写Core Foundation C的代码。 不应该: enum GlobalConstants {
kMaxPinSize = 5,
kMaxPinCount = 500,
};
Case语句大括号在case语句中并不是必须的,除非编译器强制要求。当一个case语句包含多行代码时,大括号应该加上。 switch (condition) {
case 1:
// ...
break;
case 2: {
// ...
// Multi-line example using braces
break;
}
case 3:
// ...
break;
default:
// ...
break;
}
有很多次,当相同代码被多个cases使用时,一个fall-through应该被使用。一个fall-through就是在case最后移除'break'语句,这样就能够允许执行流程跳转到下一个case值。为了代码更加清晰,一个fall-through需要注释一下。 switch (condition) {
case 1:
// ** fall-through! **
case 2:
// code executed for values 1 and 2
break;
default:
// ...
break;
}
当在switch使用枚举类型时,'default'是不需要的。例如: RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;
switch (menuType) {
case RWTLeftMenuTopItemMain:
// ...
break;
case RWTLeftMenuTopItemShows:
// ...
break;
case RWTLeftMenuTopItemSchedule:
// ...
break;
}
私有属性私有属性应该在类的实现文件中的类扩展(匿名分类)中声明,命名分类(比如 例如: @interface RWTDetailViewController ()
@property (strong, nonatomic) GADBannerView *googleAdView;
@property (strong, nonatomic) ADBannerView *iAdView;
@property (strong, nonatomic) UIWebView *adXWebView;
@end
布尔值Objective-C使用 这是为了在不同文件保持一致性和在视觉上更加简洁而考虑。 应该: if (someObject) {}
if (![anotherObject boolValue]) {} 不应该: if (someObject == nil) {}
if ([anotherObject boolValue] == NO) {}
if (isAwesome == YES) {} // Never do this.
if (isAwesome == true) {} // Never do this. 如果 @property (assign, getter=isEditable) BOOL editable; 文字和例子从这里引用Cocoa Naming Guidelines
条件语句条件语句主体为了防止出错应该使用大括号包围,即使条件语句主体能够不用大括号编写(如,只用一行代码)。这些错误包括添加第二行代码和期望它成为if语句;还有,even more dangerous defect可能发生在if语句里面一行代码被注释了,然后下一行代码不知不觉地成为if语句的一部分。除此之外,这种风格与其他条件语句的风格保持一致,所以更加容易阅读。 应该: if (!error) {
return success;
} 不应该: if (!error)
return success; 或 if (!error) return success;
三元操作符当需要提高代码的清晰性和简洁性时,三元操作符 Non-boolean的变量与某东西比较,加上括号()会提高可读性。如果被比较的变量是boolean类型,那么就不需要括号。 应该: NSInteger value = 5;
result = (value != 0) ? x : y;
BOOL isHorizontal = YES;
result = isHorizontal ? x : y; 不应该: result = a > b ? x = c > d ? c : d : y;
Init方法Init方法应该遵循Apple生成代码模板的命名规则。返回类型应该使用 - (instancetype)init {
self = [super init];
if (self) {
// ...
}
return self;
} 查看关于instancetype的文章Class Constructor Methods
类构造方法当类构造方法被使用时,它应该返回类型是 @interface Airplane
+ (instancetype)airplaneWithType:(RWTAirplaneType)type;
@end 关于更多instancetype信息,请查看NSHipster.com
CGRect函数当访问
应该: 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); 不应该: 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 };
黄金路径当使用条件语句编码时,左手边的代码应该是"golden" 或 "happy"路径。也就是不要嵌套 应该: - (void)someMethod {
if (![someOther boolValue]) {
return;
}
//Do something important
} 不应该: - (void)someMethod {
if ([someOther boolValue]) {
//Do something important
}
}
错误处理当方法通过引用来返回一个错误参数,判断返回值而不是错误变量。 应该: |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论