Objective-C规范建议

    xiaoxiao2021-03-25  95

    文章目录

    工程结构头文件常量对于#define宏命名枚举类型代码组织注释代码命名函数(Method)初始化方法单例模式Error处理黄金路径(GoldenPath)尤达表达式三元运算符布尔值使用NSInteger分类 没有规矩不成方圆。说说我比较推崇的代码规范。求同存异,别的规范也是可取的,具体问题具体分析。

    工程结构

    为整个工程创建 workspace

    合理的工程目录结构。

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

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

    Vendors:第三方库。不建议将三方库直接添加进工程,建议使用cocoapods管理。

    先按业务划分,再按照MV-X来划分。方便解耦,模块化。 将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; 命名

    若常量局限于某“编译单元”(translation unit,也就是“实现文件”,implementation file)之内,则在前面加字母k;

    若常量在类之外可见,则通常以类名为前缀。

    static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock"; 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"; Notifications [Name of associated class] + [Did | Will] + [UniquePartOfName] + Notification

    例如:

    NSApplicationDidBecomeActiveNotification NSWindowDidMiniaturizeNotification NSTextViewDidChangeSelectionNotification NSColorPanelColorDidChangeNotification Exceptions [Prefix] + [UniquePartOfName] + Exception

    例如:

    NSColorListIOException NSColorListNotEditableException NSDraggingException NSFontUnavailableException NSIllegalSelectorException

    对于#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.

    一般情况下,不要缩写名字,即使它们很长。少数一部分缩写是非常通用的,也有很长的使用历史。可用缩写

    AbbreviationMeaning and commentsallocAllocate.appApplication. For example, NSApp the global application object. However, “application” is spelled out in delegate methods, notifications, and so on…calcCalculate…deallocDeallocate.funcFunction.horizHorizontal.infoInformation.initInitialize (for methods that initialize new objects).intInteger (in the context of a C int—for an NSInteger value, use integer).maxMaximum.minMinimum.msgMessage.nibInterface Builder archive.pboardPasteboard (but only in constants).rectRectangle.RepRepresentation (used in class name such as NSBitmapImageRep)…tempTemporary.vertVertical.

    你也可以使用下面这些在计算机行业公认的专业术语: ASCII PDF XML HTML URL RTF HTTP TIFF JPG PNG GIF LZW ROM RGB CMYK MIDI FTP


    初始化方法

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

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

    单例模式

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

    static id sharedInstance = nil; + (instancetype)sharedInstance{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } //重写+ allocWithZone:此方法在调用alloc时必会调用.use object initializers instead + (instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [super allocWithZone:zone]; }); return sharedInstance; } //对于单例,应该无论以何种方式创建都应该只有一份内存的, 对于ARC的创建的方法还有copy,mutableCopy,但必须遵守协议<NSCopying,NSMutableCopying> , 执行copy,MutableCopy的时候必定会执行copyWithZone,mutableCopyWithZone - (instancetype)copyWithZone:(NSZone *)zone { return sharedInstance; } - (instancetype)mutableCopyWithZone:(NSZone *)zone { return sharedInstance; } //暂不考虑MRC

    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的话,可能不够大而造成崩溃。


    分类

    没有命名空间的概念。在分类中的所有方法都加上特定前缀,前缀需小写。如

    NSObject+XSTest.h @interface NSObject (XSTest) - (BOOL)xs_isEmptyObject; @end

    这里为分类名以及分类中的方法加上XS的前缀。


    #摘录 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 https://juejin.im/entry/583a9eafa22b9d006c0eae3c https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html https://www.jianshu.com/p/06cc78e8b8b6

    转载请注明原文地址: https://ju.6miu.com/read-14369.html

    最新回复(0)