iOS架构iOS 进阶方法论GitHub 中文社区

11.Objective-C 编码规范指南

2016-07-26  本文已影响203人  Liwx

@(〓〓 iOS-实用技术)[Objective-C编码规范]


目录


项目工程结构


代码结构

#pragma mark - Lifecycle (生命周期)
- (void)dealloc {}

- (instancetype)init {}

- (void)viewDidLoad {}

- (void)viewWillAppear:(BOOL)animated {}

- (void)didReceiveMemoryWarning {}


#pragma mark - Private (私有方法,比如初始控件设置方法/类内部业务处理方法)
- (CGFloat)setupTableView {}


#pragma mark - Public (对外公开方法)
- (CGFloat)reloadAllData {}


#pragma mark - Network (加载网络数据)
- (void)loadMoreData {}
- (void)loadNewData {}
- (void)loadOtherData {}


#pragma mark - Property Setter/Getter (成员属性的setter和getter方法)
- (void)setCustomProperty:(id)value {}

- (id)customProperty {}


#pragma mark - Events (UIControl响应函数,如按钮点击事件)
- (void)saveButtonClick:(UIButton *)saveButton {}


#pragma mark - KVO/Notification (KVO/通知响应函数)
- (void)dataSourceRefreshNotification:(NSNotification *)notification {}

- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context {}


#pragma mark - Protocol/Delegate 如UITableViewDataSource/UITableViewDelegate (协议和代理)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {}


#pragma mark - LazyLoad (懒加载)
- (UILabel *)nameLabel {}


#pragma mark - Other (其他)
- (id)copyWithZone:(NSZone *)zone {}
- (NSString *)description {}


项目Xode相关配置


代码缩进配置

XCode->Preferences->Text Editing->Indentation中进行如下设置:
ps. 设置成4个,是因为Xcode的默认缩进是4个空格。

01.代码格式化配置.png

代码行号显示配置

勾选上XCode->Preferences->Text Editing->Editing中的Line numbers,开启行号提示。

02.代码行号显示配置.png

项目编码建议

勾选XCode->Preferences->Text Editing->Editing,并将长度设置成120个字符来打开行宽指示。设置成功时Xcode会出现一条竖线! (可选配置)


注释


方法注释

// .m文件
// 按钮点击事件处理 (非对外公开的方法)
- (void)saveButtonClick:(UIButton *)saveButton {
    NSLog(@"Hello Liwx");               // 打印日志
    NSLog(@"Hello Liwx");               // 打印日志
}

/** 刷新全部数据 (对外公开的方法)*/
- (void)reloadAllData {
    //Do Something
}

// .h文件
/** 刷新全部数据 (对外公开的方法)*/
- (void)reloadAllData;

属性注释

@interface ViewController () 

/** 时间 */
@property (nonatomic, copy) NSString *time;

@end
03.外部属性注释提示.png

命名与编码规范


类名命名规则


协议编码规则

// 协议声明协议名称、尖括号之间不留空格
@protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>

@end
// 定义属性遵守协议,不留空格
@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;


控件/控制器定义命名规则

// 建议使用控件全称命名
/** 名称Label */
@property (nonatomic, weak) UILabel *nameLabel;
/** 保存Button */
@property (nonatomic, weak) UIButton *saveButton;

// 不建议控件名使用缩写
/** 名称Label */
@property (nonatomic, weak) UILabel *nameLbl;
/** 保存Button */
@property (nonatomic, weak) UIButton *saveBtn;

// TableViewCell后缀缩写为TvCell
TopicTableViewCell *topicTvCell = nil;
// CollectionViewCell后缀缩写为CvCell
ItemCollectionViewCell *itemCvCell = nil;
// ViewController可缩写为Vc
HomeViewController *homeVc = nil;

方法


方法名和参数命名规则

如:- (BOOL)isFileExistedAtPath:(NSString *)filePath;

// 正确
- (BOOL)canHide;
- (BOOL)shouldRefreshData;
- (void)willChangeData

方法声明和编码规范

- (instancetype)initwithTitle:(NSString *)title;    // 正确
-(instancetype)initwithTitle:(NSString *)title;     // 错误
- (instancetype) initwithTitle:(NSString *)title;   // 错误
- (instancetype)initwithTitle: (NSString *)title;   // 错误
- (instancetype)initwithTitle:(NSString *) title;   // 错误

如:convertPoint:fromRect: 或者 replaceCharactersInRange:withString:

// 正确
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
// 错误
- (instancetype)initWithNibName:(NSString *)nibNameOrNil andBundle:(NSBundle *)nibBundleOrNil;
- (CGFloat)setupTableView {
    // Do Something
}

方法调用父类方法编码规则

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    // Do Something
}

函数

CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)


变量

成员属性编码规则

// 成员变量声明
/** 标题Label (正确) */
@property (nonatomic, copy) NSString *titleLabel;
/** 标题Label (错误) */
@property (nonatomic, copy) NSString *titleLbl;
/** 标题Label (错误) */
@property(nonatomic, copy) NSString *titleLabel;
/** 标题Label (错误) */
@property (nonatomic,copy) NSString *titleLabel;
/** 标题Label (错误) */
@property (copy, nonatomic) NSString *titleLabel;

// 局部变量声明
NSString *titleLabel = nil;     //  正确
NSString* titleLabel = nil;     //  错误
NSString * titleLabel = nil;    //  错误
NSString*titleLabel = nil;      //  错误
/** 名称 */
@property (nonatomic, copy) NSString *name;

// 访问成员属性时,优先使用点语法
self.name = @"Liwx";
self.name = @"Liwx";    // 正确
self.name= @"Liwx";     // 错误
self.name=@"Liwx";      // 错误

@property (assign, getter = isSelected) BOOL selected;

// 正确
@property (copy,nonatomic) UserStatus *userStatus;
// 错误
@property (copy,nonatomic) NSString *userStatus;

常量


Foundation框架常量赋值规则

// 正确
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"}; 
NSNumber *shouldUseLiterals = @YES; 
NSNumber *buildingZIPCode = @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 *zipCode = [NSNumber numberWithInteger:10018];

定义普通常量以字母k开头

// 普通常量定义
NSString * const kUserKey = @"kUserKey";
CGFloat const kTopViewHeight = 50;

static关键字保证变量只有文件作用域,可以避免变量名重名造成的链接错误问题。

如: static CGFloat const RWImageThumbnailHeight = 50.0;


枚举与宏定义


枚举编码规则

因为NS_ENUMNS_OPTIONS都提供了类型检查;


NS_ENUM定义普通枚举

// 应用皮肤样式
typedef NS_ENUM(NSInteger, AppStyle) {
    AppStyleLight = 0,              // 白天模式
    AppStyleDark = 1                // 夜间模式
};

NS_OPTIONS定义位枚举

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,         // 注释
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,    // 注释
    UIViewAutoresizingFlexibleWidth        = 1 << 1,    // 注释
    ...
};

通知和异常


通知NSNotification常量命名规则

// .h文件
// 全局通知声明时需加上UIKIT_EXTERN关键字
UIKIT_EXTERN NSString *const UIKeyboardDidChangeFrameNotification ;

// .m文件, 通知常量名和值必须保持一致
NSString *const UIKeyboardDidChangeFrameNotification = @"UIKeyboardDidChangeFrameNotification";

异常命名规则

如:NSColorListIOException


布尔值

// 正确
if (self.isLogin) {}
// 错误
if (self.isLogin == YES) {}
// 正确
- (BOOL)isLogin {
    return self.userToken.length != 0 ? YES : NO;
}
// 错误
- (BOOL)isLogin {
    return self.userToken.length;
}

条件语句


if else 条件语句

// 正确
if (isLogin) {
    // Do Something
} else {
    // DO Something
}

// 错误
if (isLogin) 
{
    // Do Something
} 
else {
    // DO Something
}
// 正确
if (error == nil) {
    return success;
}
// 错误
if (error == nil)
    return success;
// 优先考虑可以跳出的流程
if (!a) {
    return;
}

if (!b) {
    return;
}

if (!c) {
    return;
}

// 不建议使用嵌套的方式
if (a) {
    if (b) {
        if (c) {
        } 
    } 
} 
// 正确
NSInteger value = 5;
result = (value != 0) ? x : y;
// 错误
result = a > b ? x = c > d ? c : d : y;

switch case 语句

RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;

switch (menuType) {
  case RWTLeftMenuTopItemMain:
    // ...
    break;
  case RWTLeftMenuTopItemShows:
    // ...
    break;
  case RWTLeftMenuTopItemSchedule:
    // ...
    break;
}

其他规则


初始化方法(构造方法)规则


直接放回对应数据时,无需添加get, calc单词

- (CGFloat)cellHeight;      // 正确
- (CGFloat)getCellHeight;   // 错误
- (CGFloat)calcCellHeight;  // 错误

单例的声明和使用规则

+ (instancetype)sharedInstance {
    static id sharedInstance = nil;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    
    return sharedInstance;
}
// 正确
[UIApplication sharedApplication].delegate;
// 错误
UIApplication.sharedApplication.delegate;

设置常用属性,直接使用点语法

// 正确
self.view.backgroundColor = [UIColor redColor];
// 错误
[self.view setBackgroundColor:[UIColor redColor]];

协议和代理方法命名规则


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath;


可以使用({})语法模块化设置控件属性(可选)

// 前提: 该属性需由strong修饰
/** 名称Label */
@property (nonatomic, strong) UILabel *nameLabel;

self.nameLabel = ({
        UILabel *label = [[UILabel alloc] init];
        label.textAlignment = NSTextAlignmentCenter;
        label.font = [UIFont systemFontOfSize:12];
        label.textColor = [UIColor orangeColor];
        label;
    });

上一篇 下一篇

猜你喜欢

热点阅读