💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、豆包、星火、月之暗面及文生图、文生视频 广告
# iOS 我的代码规范 [TOC] *** # 命名部分 *** # 项目名 强迫症患者感觉不对的项目名: MsAddressBook Ms_AddressBook MS_SDFAddressBook -前缀太长没有意义 msAddressBook MS_AddressBook -这个说不上不对。 MSAddressBookTest -用test还是用demo呢? 总结下,大概遵守下列规则 - 前缀+描述性+功能(+Demo);如 MSSimpleRecordDemo - 前缀大写;前缀最好是有意义的、简约的字母。 - 中间不使用下划线。 - 如果是Demo,则后缀使用Demo,不使用Test。 如:MSAddressBook,MSAddressBookDemo。 *** # 类名 看着不舒服的类名: LiMakingVC LiMyJLviewController --view 的首字母应该大写 Ky_GradeVc --前缀为什么要小写,要不要“_” CardIconEditViewController --会不会太长 感觉正确的类名: # 方法名 让人知道是哪个模块+哪个功能的 ## { 到底换行,还是不换行 # 属性名字 # 扩展类 # 变量名字 # 宏定义 # 其他 ## Masonry 中 leading 和 left不混用 leading 和 trailing 一起用,left 和 right 一起用,不混合搭配。 *** # 控制器内代码结构 分为几个层级 1、控制器生命周期方法 2、delegate方法 3、私有方法:网络请求、逻辑等 4、懒加载 ![控制器方法顺序](/Users/MelissaShu/Documents/iOS/控制器方法顺序.png) *** # 语法部分 类型 使用到整形变量时,建议使用NSInteger NSUInteger,不建议使用int,uint 。 使用float时,建议使用CGFloat 常量 建议 static NSString *const PLMessageCountChanageNotificationName = @"MessageCountChanageNotification" static NSUInteger const PLRetryMaxCount = 5 不建议 #define PLMessageCountChanageNotificationName @"MessageCountChanageNotification" #define PLRetryMaxCount 5 变量 遵循驼峰模式即可 对于实例变量建议以下划线开始命名 @interface Foo() { NSString *_name } @end 对于局部变量建议不要以下划线开头, 避免误解变量的作用域 不建议 - (void)uploadVideo { NSString *_name = @""; } @end 字面值 对于NSString, NSDictionary, NSArray, 以及 NSNumber 支持语法糖 建议 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]; 枚举 当使用 enum 的时候,建议使用新的固定的基础类型定义,因为它有更强大的类型检查和代码补全。 SDK 现在有一个 宏来鼓励和促进使用固定类型定义 - NS_ENUM() 建议 typedef NS_ENUM(NSInteger, UIViewAnimationCurve) { UIViewAnimationCurveEaseInOut, // slow at beginning and end UIViewAnimationCurveEaseIn, // slow at beginning UIViewAnimationCurveEaseOut, // slow at end UIViewAnimationCurveLinear, }; typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutoresizingFlexibleWidth = 1 << 1, UIViewAutoresizingFlexibleRightMargin = 1 << 2, UIViewAutoresizingFlexibleTopMargin = 1 << 3, UIViewAutoresizingFlexibleHeight = 1 << 4, UIViewAutoresizingFlexibleBottomMargin = 1 << 5 }; 不建议 enum UIViewAnimationCurve { UIViewAnimationCurveEaseInOut, // slow at beginning and end UIViewAnimationCurveEaseIn, // slow at beginning UIViewAnimationCurveEaseOut, // slow at end UIViewAnimationCurveLinear, }; 控制语句 关于if 一行代码: 条件语句体应该总是被大括号包围。尽管有时候你可以不使用大括号(比如,条件语句体只有一行内容),但是这样做会带来问题隐患。比如,增加一行代码时,你可能会误以为它是 if 语句体里面的。此外,更危险的是,如果把 if 后面的那行代码注释掉,之后的一行代码会成为 if 语句里的代码。 建议 if (!error) { return success; } 不建议 if (!error) return success; or if (!error) return success; 多行代码: 在if中对于花括号{的处理应该趋于书写在行尾,这样控制条件和控制语句容易被视为一个整体。 建议 if(condition) { //... } else { //... } 不建议 if(condition) { //.. } else { //.. } 尤达表达式 不要使用尤达表达式。尤达表达式是指,拿一个常量去和变量比较而不是拿变量去和常量比较。它就像是在表达 “蓝色是不是天空的颜色” 或者 “高个是不是这个男人的属性” 而不是 “天空是不是蓝的” 或者 “这个男人是不是高个子的” 推荐 if ([myValue isEqual:@42]) { ... 不推荐 if ([@42 isEqual:myValue]) { ... 多层嵌套 在使用条件语句编程时,不要嵌套 if 语句。使用多个 return 可以避免增加循环的复杂度,并提高代码的可读性。因为方法的重要部分没有嵌套在分支里面,并且你可以很清楚地找到相关的代码。 推荐 - (void)someMethod { if (![someOther boolValue]) { return; } //Do something important } 不推荐 - (void)someMethod { if ([someOther boolValue]) { //Do something important } } 复杂的表达式 当你有一个复杂的 if 子句的时候,你应该把它们提取出来赋给一个 BOOL 变量,这样可以让逻辑更清楚,而且让每个子句的意义体现出来。 推荐 BOOL nameContainsSwift = [sessionName containsString:@"Swift"]; BOOL isCurrentYear = [sessionDateCompontents year] == 2014; BOOL isSwiftSession = nameContainsSwift && isCurrentYear; if (isSwiftSession) { // Do something very cool } 关于switch 括号不是必须的,为了代码结构层次清晰,建议加上括号。 switch(condition){ case 1: { //one line or multi-line } break; default: break; } 对于枚举类型的switch,可以不需要default UIViewAnimationCurve curveType = UIViewAnimationCurveEaseInOut; switch(curveType) { case UIViewAnimationCurveEaseInOut: { } break; case UIViewAnimationCurveEaseIn: { } break; case UIViewAnimationCurveEaseOut: { } break; case UIViewAnimationCurveLinear: { } break; } 关于for循环 对于集合类型(array,set) 建议使用 enumerateObjectsUsingBlock NSArray *nameArray = @[@"Kita","jonas"]; [nameArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { //... }]; 其次可以选择for in 如果不需要索引的话 for(NSString *name in nameArray) { //... } 三目运算符 三目运算符 ? 应该只用在它能让代码更加清楚的地方。 一个条件语句的所有的变量应该是已经被求值了的。类似 if 语句,计算多个条件子句通常会让语句更加难以理解。或者可以把它们重构到实例变量里面。 推荐 result = a > b ? x : y; 不推荐 result = a > b ? x = c > d ? c : d : y; 属性 对于属性修饰符要全都指示出来,对于纯量类型默认是(atomic,assign),对于对象类型默认是(atomic,strong)。权限修饰符默认readwrite可以不写,一般情况下属性都是readwrite,对于只读属性需要写明readonly 对于有可变类型的类(NSString,NSArray,NSDictionary,NSSet) 建议使用copy,是因为有可能引用可变对象 建议 @property (nonatomic, copy) NSString *name; @property (nonatomic, strong) UIView *containerView; 不建议 @property(nonatomic,strong) NSString *name; @property(nonatomic) UIView *containerView; 方法 方法类型(-/+)后需要空一格 建议 - (void)setTitle:(nullable NSString *)title forState:(UIControlState)state; 不建议 -(void)setTitle:(nullable NSString *)title forState:(UIControlState)state; 注释 文件注释 注释是代码可读性的关键,最好的代码应该自成文档。 其他注释(类注释,方法注释等) xcode8 建议使用自带注释快捷键 command+option+/ 代码结构组织 viewController类的建议 ``` @property (nonatomic, strong) UITableView *tableView; ... pragma mark - Life cycle (生命周期) - (instancetype)init {} - (void)viewDidLoad {} - (void)viewWillAppear:(BOOL)animated {} - (void)didReceiveMemoryWarning {} - (void)dealloc {} pragma mark - UITableViewDelegate (代理协议) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {} ... pragma mark - LMFootViewButtonDelegate(代理协议) -(void)footViewDidSelectedButton:(UIButton *)sender andIndex:(NSInteger)index andButtonTitle:(NSString *)titleText{} ... pragma mark - IBActions(event response) - (IBAction)submitData:(id)sender {} ... pragma mark - Private Methods - (void)privateMethod {} ... pragma mark - Getter and Setter - (NSString *)name; - (void)setName:(NSString *)name; ``` 使用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 }; Tips 行宽 尽量保持在100以内,具体设置如下: Xcode->Preferences->Text Editing->Page guide at column *** # Pod部分 *** # 部分 *** # 部分 *** # 部分