[关闭]
@xifenglang-33250 2018-12-03T17:36:49.000000Z 字数 6458 阅读 707

代码Review-2018.12.1

森特网


1、--------------方法命名习惯------------------------------

例子:

  1. -(void)viewWillAppear:(BOOL)animated {
  2. [super viewWillAppear:animated];
  3. self.api.queryName = @"";
  4. [self loadData];
  5. }
  6. - (void) didSelectedRecentWithRow:(NSInteger)row {
  7. self.api.docType = row * 10;
  8. [self.tableView.mj_header beginRefreshing];
  9. }

方法命名中使用空格的标准写法

  1. "-"后面接一个空格
  2. "(void)"后不接空格
  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. [self setupUI];
  4. [self.tableView.mj_header beginRefreshing];
  5. }

2、--------------属性命名习惯----------------------------

例子:

  1. @property (nonatomic, strong) NSArray <HTRegionModel *> *streets;
  2. @property (nonatomic, assign) NSInteger index0;
  3. @property (nonatomic, assign) NSInteger index1;
  4. @property (nonatomic, assign) NSInteger index2;
  5. @property (nonatomic, assign) NSInteger index3;
  6. - (void)setStreets:(NSArray<HTRegionModel *> *)streets
  7. {
  8. _streets = streets;
  9. if (_streets.count > 0) {
  10. [self addBtnAndTableView];
  11. [self moveLine];
  12. self.lastBtn.selected = NO;
  13. UITableView *tableView = (UITableView *)self.areaScrollView.subviews[self.lastBtn.tag];
  14. [tableView reloadData];
  15. }else {
  16. [self moveLine];
  17. self.lastBtn.selected = NO;
  18. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  19. [self hidenAreaView];
  20. if (self.delegate) {
  21. [self.delegate selectedIndexProvice:_index0 city:_index1 district:_index2 street:-1];
  22. }
  23. });
  24. }
  25. }

1、方法名尾部不应在“ {”前面换行,而是“ {”后换行,并且"{"前有个空格
2、声明NSArray、NSDictionary、NSString等不可变容器类型属性,应用copy修饰
3、重写NSArray、NSDictionary、NSString等不可变容器类型属性,setter里面应该赋值copy后的值,ARC声明block属性建议用copy,尽可能跟MRC写法逻辑保持一致。
4、在Block实现中调用成员变量_index0、_index1、_index2编译时会有警告,应改成self.proviceIndex
5、声明成员变量避免使用123等数字,可读性差,命名应追求顾名思义,适当的添加注释。index0应改成proviceIndex

修改后

  1. @property (nonatomic, copy) NSArray <HTRegionModel *> *streets;
  2. @property (nonatomic, assign) NSUInteger proviceIndex;
  3. - (void)setStreets:(NSArray<HTRegionModel *> *)streets {
  4. _streets = streets.copy;
  5. if (streets.count > 0) {
  6. [self addBtnAndTableView];
  7. [self moveLine];
  8. self.lastBtn.selected = NO;
  9. UITableView *tableView = (UITableView *)self.areaScrollView.subviews[self.lastBtn.tag];
  10. [tableView reloadData];
  11. } else {
  12. [self moveLine];
  13. self.lastBtn.selected = NO;
  14. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  15. [self hidesAreaView];
  16. if (self.delegate) {
  17. [self.delegate selectedIndexProvice:self.proviceIndex city:self.cityIndex district:self.districtIndex street:-1];
  18. }
  19. });
  20. }
  21. }

其中涉及到的协议方法还可以再改

  1. @protocol HTSelectedAddrViewDelegate
  2. /// 选择后的下标
  3. - (void) selectedIndexProvice:(NSInteger)index0 city:(NSInteger)index1 district:(NSInteger)index2 street:(NSInteger)index3;
  4. @end

业务处理层需要的是直接可用的结果(HTRegionModel),而不是拿到下标去查数据。
应改成

  1. @protocol HTSelectedAddrViewDelegate
  2. - (void)didSelectedProvice:(HTRegionModel *)provice city:(HTRegionModel *)city district:(HTRegionModel *)district street:(HTRegionModel *)street;
  3. /// 或者
  4. - (void)addressSelectorView:(HTSelectedAddrView *)selectorView didSelectedProvice:(HTRegionModel *)provice city:(HTRegionModel *)city district:(HTRegionModel *)district street:(HTRegionModel *)street;
  5. @end

3、--------------避免使用透明背景色------------------------------------

渲染透明色和layer.cornerRadius倒圆角会明显降低FPS,初始化View应当设置背景色,XIB亦然,列表中出现圆角view尽量用贝塞尔曲线绘制图片。

  1. [[UILabel alloc] init]
  2. [[UIImageView alloc] init];
  3. ...

4、--------------利用函数实现跨类跨模块复用代码-----------------------------

修改前:

  1. NSInteger docType = [stockOutModel.docType integerValue];
  2. if (docType == 0) {
  3. self.stateLabel.text= @"待处理";
  4. }else if (docType == 10) {
  5. self.stateLabel.text= @"待拣货";
  6. }else if (docType == 20) {
  7. self.stateLabel.text= @"复核完成";
  8. }else if (docType == 30) {
  9. self.stateLabel.text= @"已发运";
  10. }else if (docType == 40) {
  11. self.stateLabel.text= @"已取消";
  12. }else if (docType == 50) {
  13. self.stateLabel.text= @"已关闭";
  14. }else {
  15. self.stateLabel.text= @"未知";
  16. }

修改后:
优势:
1、方便改文案,不用多个地方改,容易出BUG
2、复用代码,减少垃圾代码
3、提炼更专一的函数,职能细分,方便重构

  1. *.h
  2. /** 根据状态码获取出库状态描述 */
  3. UIKIT_EXTERN NSString * ERPStockOutStatusNameWith(NSUInteger status);
  4. *.m
  5. NSString * ERPStockOutStatusNameWith(NSUInteger status) {
  6. switch (status) {
  7. case 0:return @"待处理";
  8. case 10:return @"待拣货";
  9. case 20:return @"复核完成";
  10. case 30:return @"已发运";
  11. case 40:return @"已取消";
  12. case 50:return @"已关闭";
  13. default:return [NSString stringWithFormat:@"未知状态%ld",status];
  14. }
  15. }
  16. 其它.m
  17. NSInteger docType = [stockOutModel.docType integerValue];
  18. self.stateLabel.text = ERPStockOutStatusNameWith(docType);

5、--------------ERPStockReportItemView.h修改案例-------------------

修改前:

  1. @protocol ERPStockReportItemViewDelegate <NSObject>
  2. - (void) didItemWithRow:(NSInteger)row;
  3. @end
  4. @interface ERPStockReportItemView : UIView
  5. - (instancetype)initWithTitles:(NSArray *)titles;
  6. @property (nonatomic, weak) id <ERPStockReportItemViewDelegate> delegate;
  7. @end

修改后

  1. @protocol ERPStockReportItemViewDelegate <NSObject>
  2. /// 通过方法名不能看懂方法的作用时,就应该修改命名或者补加注释
  3. /// 以stockReportItemView开头,主要是为了表明协议方法的调用者,在实现方法的类可以明显的区分。仿UITableViewDelegate
  4. - (void)stockReportItemView:(ERPStockReportItemView *)itemView didSelectedItemAtRow:(NSInteger)row;
  5. @end
  6. @interface ERPStockReportItemView : UIView
  7. // NS_UNAVAILABLE会禁用外部调用实例化,NS_DESIGNATED_INITIALIZER 即指定的实例化方法
  8. - (instancetype)init NS_UNAVAILABLE;
  9. - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
  10. - (instancetype)initWithTitles:(NSArray *)titles NS_DESIGNATED_INITIALIZER;
  11. @property (nonatomic, weak) id <ERPStockReportItemViewDelegate> delegate;
  12. @end

5、--------------注册监听和移除监听-------------------

案例

  1. ERPStockTransferViewController.m
  2. - (void)viewDidAppear:(BOOL)animated {
  3. [super viewDidAppear:animated];
  4. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(freshNotification) name:stockAllotNotifacation object:nil];
  5. }

缺点:在viewDidAppear中多次注册监听,.m文件里面没有移除监听的代码

使用KVO时一定要移除监听,Notification大多数情况不移除监听不会闪退,但不代表绝对安全,而应本着谁添加谁移除的原则写相关代码,这块的关注点是代码习惯和代码质量。
修改方向:
1. 在viewDidLoad中注册一次监听,在控制器生命周期将结束时移除监听,比如以下2个方法

  1. - (void)stw_viewControllerWillDismissFromStack {}
  2. - (void)dealloc {}
  1. 如果在viewWillAppear、viewDidAppear添加监听,就应该在viewWillDisappear、viewDidDisappear移除监听,监听和结束监听的时机应该是对应的。

  2. 将KVO或者Notification做成自动化移除

6、--------------轻量化ViewController-------------------

参考:
1. objc china的一篇译文《Lighter View Controllers》
2. iOS 开发中的 Self-Manager 模式

尽量将控制器的代码控制在500行以内,甚至300行以内,避免重复写无营养的代码。有个同行说过一句话:把垃圾代码放在一起

n、--------------其它-------------------

n.1

  1. @property (nonatomic, strong) NSArray*storeExportDetailAppResDtos;

修改后:
1、NSArray*类型,strong换成copy;
2、storeExportDetailAppResDtos命名过长,去掉无意义的字段,改成storeExportDetail,这个地方甚至涉及到字段的前后端分离。
3、声明Array的元素类型

  1. @property (nonatomic, copy) NSArray <ERPStockOutGoodModel *> *storeExportDetail;

n.2

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注