美文网首页
iOS代码规范,风格纠错

iOS代码规范,风格纠错

作者: Felix的笔头 | 来源:发表于2018-05-11 16:44 被阅读0次

    风格纠错

    1438582884375682.png

    下面对具体修改的地方,分两部分做下介绍:硬伤部分和优化部分 。因为硬伤部分没什么技术含量,为了节省大家时间,放在后面讲,大神请直接看优化部分。

    一:优化部分

    1)enum建议使用 NS_ENUM 和 NS_OPTIONS 宏来定义枚举类型,参见官方的 Adopting Modern Objective-C 一文:

    //定义一个枚举
    typedef NS_ENUM(NSInteger, CYLSex) {
        CYLSexMan,
        CYLSexWoman
    };
    

    2)age属性的类型:应避免使用基本类型,建议使Foundation数据类型,对应关系如下:

    int -> NSInteger
      unsigned -> NSUInteger
      float -> CGFloat
      动画时间 -> NSTimeInterval
    

    同时考虑到age的特点,应使用NSUInteger,而非int。 这样做的是基于64-bit 适配考虑,详情可参考出题者的博文《64-bit Tips》。

    3)如果工程项目非常庞大,需要拆分成不同的模块,可以在类、typedef宏命名的时候使用前缀。

    4)doLogIn方法不应写在该类中:虽然LogIn的命名不太清晰,但笔者猜测是login的意思,而登录操作属于业务逻辑,观察类名UserModel,以及属性的命名方式,应该使用的是MVC模式,并非MVVM,在MVC中业务逻辑不应当写在Model中。(如果是MVVM,抛开命名规范,UserModel这个类可能对应的是用户注册页面,如果有特殊的业务需求,比如:login对应的应当是注册并登录的一个Button,出现login方法也可能是合理的。)

    5)doLogIn方法命名不规范:添加了多余的动词前缀。 请牢记:

    如果方法表示让对象执行一个动作,使用动词打头来命名,注意不要使用do,does这种多余的关键字,动词本身的暗示就足够了。

    6)-(id)initUserModelWithUserName: (NSString*)name withAge:(int)age;方法中不要用with来连接两个参数:withAge:应当换为age:,age:已经足以清晰说明参数的作用,也不建议用andAge::通常情况下,即使有类似withA:withB:的命名需求,也通常是使用withA:andB:这种命名,用来表示方法执行了两个相对独立的操作(从设计上来说,这时候也可以拆分成两个独立的方法),它不应该用作阐明有多个参数,比如下面的:

    //错误,不要使用"and"来连接参数
    - (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
    //错误,不要使用"and"来阐明有多个参数
    - (instancetype)initWithName:(CGFloat)width andAge:(CGFloat)height;
    //正确,使用"and"来表示两个相对独立的操作
    - (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;
    

    7)由于字符串值可能会改变,所以要把相关属性的“内存管理语义”声明为copy。(原因在下文有详细论述:用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?)

    8)“性别”(sex)属性的:该类中只给出了一种“初始化方法” (initializer)用于设置“姓名”(Name)和“年龄”(Age)的初始值,那如何对“性别”(Sex)初始化?

    Objective-C 有 designated 和 secondary 初始化方法的观念。 designated 初始化方法是提供所有的参数,secondary 初始化方法是一个或多个,并且提供一个或者更多的默认参数来调用 designated 初始化方法的初始化方法。举例说明:

      @implementation CYLUser
      - (instancetype)initWithName:(NSString *)name
                               age:(int)age
                               sex:(CYLSex)sex {
          if(self = [super init]) {
              _name = [name copy];
              _age = age;
              _sex = sex;
          }
          return self;
      }
      - (instancetype)initWithName:(NSString *)name
                               age:(int)age {
          return [self initWithName:name age:age sex:nil];
      }
      @end
    

    上面的代码中initWithName:age:sex: 就是 designated 初始化方法,另外的是 secondary 初始化方法。因为仅仅是调用类实现的 designated 初始化方法。

    因为出题者没有给出.m文件,所以有两种猜测:1:本来打算只设计一个designated 初始化方法,但漏掉了“性别”(sex)属性。那么最终的修改代码就是上文给出的第一种修改方法。2:不打算初始时初始化“性别”(sex)属性,打算后期再修改,如果是这种情况,那么应该把“性别”(sex)属性设为readwrite属性,最终给出的修改代码应该是:

    1438591341523245.png
    .h中暴露 designated 初始化方法,是为了方便子类化 (想了解更多,请戳--》 《禅与 Objective-C 编程艺术 (Zen and the Art of the Objective-C Craftsmanship 中文翻译)》。)

    9)按照接口设计的惯例,如果设计了“初始化方法” (initializer),也应当搭配一个快捷构造方法。而快捷构造方法的返回值,建议为instancetype,为保持一致性,init方法和快捷构造方法的返回类型最好都用instancetype。

    10)如果基于第一种修改方法:既然该类中已经有一个“初始化方法” (initializer),用于设置“姓名”(Name)、“年龄”(Age)和“性别”(Sex)的初始值: 那么在设计对应@property时就应该尽量使用不可变的对象:其三个属性都应该设为“只读”。用初始化方法设置好属性值之后,就不能再改变了。在本例中,仍需声明属性的“内存管理语义”。于是可以把属性的定义改成这样

    @property (nonatomic, copy, readonly) NSString *name;
    @property (nonatomic, assign, readonly) NSUInter age;
    @property (nonatomic, assign, readonly) CYLSex sex;
    

    由于是只读属性,所以编译器不会为其创建对应的“设置方法”,即便如此,我们还是要写上这些属性的语义,以此表明初始化方法在设置这些属性值时所用的方式。要是不写明语义的话,该类的调用者就不知道初始化方法里会拷贝这些属性,他们有可能会在调用初始化方法之前自行拷贝属性值。这种操作多余而且低效。

    11)initUserModelWithUserName如果改为initWithName会更加简洁,而且足够清晰。

    12)UserModel如果改为User会更加简洁,而且足够清晰。

    13)UserSex如果改为Sex会更加简洁,而且足够清晰。

    二:硬伤部分

    1)在-和(void)之间应该有一个空格

    2)enum中驼峰命名法和下划线命名法混用错误:枚举类型的命名规则和函数的命名规则相同:命名时使用驼峰命名法,勿使用下划线命名法。

    3)enum左括号前加一个空格,或者将左括号换到下一行

    4)enum右括号后加一个空格

    5)UserModel :NSObject 应为UserModel : NSObject,也就是:右侧少了一个空格。

    6)@interface与@property属性声明中间应当间隔一行。

    7)两个方法定义之间不需要换行,有时为了区分方法的功能也可间隔一行,但示例代码中间隔了两行。

    8)-(id)initUserModelWithUserName: (NSString*)name withAge:(int)age;方法中方法名与参数之间多了空格。而且- 与(id)之间少了空格。

    9)-(id)initUserModelWithUserName: (NSString)name withAge:(int)age;方法中方法名与参数之间多了空格:(NSString)name前多了空格。

    10)-(id)initUserModelWithUserName: (NSString)name withAge:(int)age;方法中(NSString)name,应为(NSString *)name,少了空格。

    11)doLogIn方法命名不清晰:笔者猜测是login的意思,应该是粗心手误造成的。

    12)第二个@property中assign和nonatomic调换位置。

    相关文章

      网友评论

          本文标题:iOS代码规范,风格纠错

          本文链接:https://www.haomeiwen.com/subject/omvylftx.html