Objective-C规范建议

没有规矩不成方圆。说说我比较推崇的代码规范。求同存异,别的规范也是可取的,具体问题具体分析。

工程结构

  • 为整个工程创建 workspace

  • 合理的工程目录结构。

    • Core:通用的机制实现类:统一的任务管理,模块管理,服务管理。

    • General:公用类和方法,包括工程内基类(Base),公用Category,公用UI组件(CustomUI),公用辅助方法(Helper)和宏定义(Macro)。

    • Vendors:第三方库。

    • 先按业务划分,再按照MVC来划分。方便解耦,模块化。
      将TableViewCell放在View目录,把具体的ViewController放在Controller目录,图片等资源放到Resource目录,工具类放到Utils目录。


头文件

#import的顺序按照:系统类、第三方类、自己类

 #import <系统库> 
 #import <系统库> 

 #import <第三方库> 
 #import <第三方库> 

 #import “其他类”

常量

  • 常量用static,不使用#define

static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";

static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3;
  • 开头用k标识

    字符k+模板名字首字母大写+作用名称,防止和其他的重复

NSString * const kTTTStrikeOutAttributeName = @"TTTStrikeOutAttribute";
  • 声明Cell的重用

    字符k+cell的名称+identifier

static NSString *const kQuestionCellIdentifier = @"kQuestionCellIdentifier";
  • const声明字符串提供外部使用

    h声明m实现且让其他的类用使用。如果导入是UIKit类就使用UIKIT_EXTERN,如果是Founction使用关键词FOUNDATION_EXTERN。


//h声明

FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification;


//m实现

NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";

对于#define宏命名

单词全部的大写,单词之间用_分割。

#define RCT_EXPORT_SHADOW_PROPERTY(name, type) \
+ (NSArray<NSString *> *)propConfigShadow_##name { return @[@#type]; }

枚举类型

使用NS_ENUM、NS_OPTIONS语法,不使用enum语法(除非c语言),新的语法有更强的类型检查和代码补全。

typedef NS_ENUM(NSInteger, NetworkStatus) {
    // Apple NetworkStatus Compatible Names.
    NotReachable = 0,
    ReachableViaWiFi = 2,
    ReachableViaWWAN = 1
};
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
    SDWebImageDownloaderLowPriority = 1 << 0,
    SDWebImageDownloaderProgressiveDownload = 1 << 1,
    SDWebImageDownloaderUseNSURLCache = 1 << 2,
    SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
    }

对于NS_OPTIONS类型多值用|连接,不能用+。


NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay


代码组织

使用#pragma mark - 进行分组

#pragma mark - Lifecycle

- (instancetype)init {}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}

#pragma mark - Public

- (void)publicMethod {}

#pragma mark - rewrite

- (void)fatherMethod {}

#pragma mark - Private

- (void)privateMethod {}

#pragma mark - Draw
- (void)drawRect:(CGRect)rect {}

#pragma mark - Events

- (IBAction)submitData:(id)sender {}
- (void)onBtnClicked:(id)sender {}

#pragma mark - Protocol conformance
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate

#pragma mark - Properties

- (void)setCustomProperty:(id)value {}
- (id)customProperty {}

#pragma mark - NSCopying

- (id)copyWithZone:(NSZone *)zone {}

#pragma mark - NSObject

- (NSString *)description {}

注释代码

应该尽量做到清晰可读,做到自解释。当需要注释时,注释应该更多地用来描述,为什么这样做。注释保持更新,历史的注释应该删除。

  • 可能存在问题的代码应该加上// FIXME:的注释,并详细描述(注意用半角的冒号)。

  • 需要添加逻辑的代码应该加上// TODO:,并详细描述。

  • 不是源码文件创建者修改了代码,应该在修改的代码上加上// Modified:,并写明修改人、修改时间、修改原因等信息。


命名

  • 必须尽量遵守苹果官方的命名规范,应该使用长的、描述清楚的函数名、变量名。应该使用三个字母的前缀来给类、常量进行命名。
  • 控件命名中UILabel结尾加上Label,UIImageView结尾记上ImageView等等。
@property(nonatomic,strong) UILabel  *userNameLabel;

函数(Method)

在函数签名中(函数声明或定义),在函数类型(-/+符号)后,必须有一个空格。参数之间也要有一个空格。参数的keyword不要为空。除了第一个参数,后面的参数的keyword尽量不要加with、and等连词的前缀,keyword更不应该直接用with、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.

初始化方法

返回值应该使用instancetype来代替之前的id。

- (instancetype)init {
    self = [super init];
    if (self) {
        // ...
    }
    return self;
}

单例模式

单例模式应该使用dispatch_once来保证创建时的线程安全。

+ (instancetype)sharedInstance {
  static id sharedInstance = nil;

  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedInstance = [[self alloc] init];
  });

  return sharedInstance;
}

Error处理

当函数返回NSError的引用,调用时要根据返回值进行判断,而不是NSError的值,因为苹果的一些api会往NSError中写一些垃圾数据,如果根据NSError进行判断可能会有问题。

ARC中严重不推荐使用try catch,可能内存泄露。

NSError *error;
if (![self trySomethingWithError:&error]) {
  // Handle Error
}

黄金路径(GoldenPath)

当if判断有多层嵌套,应该尽量使用黄金路径,即不符合条件的分支先返回,这样可以避免分支嵌套。

- (void)someMethod {
    if (!condition1) {
        return;
    }
    //Do something1
    if (!condition2) {
        return;
    }
    // Do something 2
}

尤达表达式

不要使用尤达表达式。

if ([myValue isEqual:@42]) {}

三元运算符

三元运算符, ?: , 应该只在它能提高代码整洁性而且逻辑清晰的情况下使用。判断条件应该只有一个,多于一个的判断条件应该用if或临时变量来写。


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);

布尔值

  • 使用YES和NO来表示布尔值。
    • true和false除了CoreFoundation和C、C++代码中,不应该被使用。
    • nil被判断为NO,没有必要与nil进行比较。
    • BOOL值可以最大可以达到8位,而YES只是被设置为1,尽量不要跟YES比较。
//应该
if (someObject) {}
if (![anotherObject boolValue]) {}
//不应该
if (someObject == nil) {}
if ([anotherObject boolValue] == NO) {}
if (isAwesome == YES) {} // Never do this.
if (isAwesome == true) {} // Never do this.
  • 如果布尔类型的属性名是一个形容词,那么属性虽然可以忽略is 前缀,但最好仍提供带is前缀的getter方法。
@property (assign, getter=isEditable) BOOL editable;

使用NSInteger

Apple的UIKit等代码一般都是用的NSInteger。NSInteger在32位系统是 int,64位系统是long 。系统的代码用的是 NSInteger 的话,你使用int的话,可能不够大而造成崩溃。


摘录

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html
http://www.aichengxu.com/ios/7566968.htm
http://reviewcode.cn/article.html?reviewId=9
http://www.cnblogs.com/netfocus/p/3896118.html
http://www.cocoachina.com/ios/20170105/18515.html
https://github.com/objc-zen/objc-zen-book

猜你喜欢

转载自blog.csdn.net/a184251289/article/details/60963728
今日推荐