IOS编码规范

作者: 面皮大师 | 来源:发表于2017-07-08 15:13 被阅读91次

    IOS开发规范

    公司新项目马上要启动,整理一篇规范,供参考。

    命名规范

    驼峰法,除第一个单词之外,其他单词首字母大写。

    属性命名

    描述性的单词+变量类型,一目了然,如:

    @property(nonatomic,weak)IBOutlet UILabel *titleLabel;

    @property(nonatomic,weak)IBOutlet UILabel *dateLabel;

    类命名

    普通功能也面类命名规范,功能模块前缀+类型/模型/管理,一目了然,如:

    MessageTableViewCell.h

    MessageTableViewCell.m

    MessageTableViewCell.xib

    MessageTableViewController.h

    MessageTableViewController.m

    MessageTableViewController.xib

    ProductViewController.h

    ProductViewController.m

    ProductViewController.xib

    ProductItem.h

    ProductItem.m

    ProductModel.h

    ProductModel.m

    UserManager.h

    UserManager.m

    NetworkManager.h

    NetworkManager.m

    方法命名

    一个规范的方法读起来应该像一句完整的话,读过之后便知函数的作用。

    执行性的方法应该以动词开头,小写字母开头。

    返回性的方法应该以返回的内容开头,但之前不要加get。如:

    -(void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;

    -(instancetype)arrayWithArray:(NSArray *)array;

    -(ProductModel *)productWithCategory:(NSString *)categoryId;

    常量命名

    对于常量的命名前面加上字母k作为标记. 如:

    static const NSTimeInterval kAnimationDuration = 0.3;

    定义作为NSDictionary或者Notification等的Key值字符串时加上const关键字, 以防止被修改. 如:

    NSString *const UIApplicationDidEnterBackgroundNotification

    枚举命名

    对于枚举类型, 经常会看到之前的C的定义方式:

    typedef enum : {
        CameraModeFront,
        CameraModeLeft,
        CameraModeRight,
    } CameraMode;
    

    作为一个iOS开发要以Objective-C的方式来定义:

    typedef NS_ENUM (NSInteger, UIViewAnimationTransition) {
        UIViewAnimationTransitionNone,
        UIViewAnimationTransitionFlipFromLeft,
        UIViewAnimationTransitionFlipFromRight,
        UIViewAnimationTransitionCurlUp,
        UIViewAnimationTransitionCurlDown,
    };
    
    

    这边需要注意的是: 枚举类型命名要加相关类名前缀并且枚举值命名要加枚举类型前缀.

    图片命名

    原则:

    1)采用单词全拼,或者大家公认无岐义的缩写(比如:nav,bg,btn等)

    2)采用“模块_功能”命名法,模块分为公共模块、私有模块。公共模块主要包括统一的背
    景、导航条、标签、按钮背景、图标、默认图等等;私有模块主要根据app的业务
    功能模块划分,比如用户中心,消息中心等。

    公共模块命名示例:

    导航条背影图片:bg_nav_bar@2x.png

    导航返回按钮正常:nav_back_normal@2x.png

    导航返回按钮选中:nav_back_selected@2x.png

    标签item背景正常:tabbar_record_normal@2x.png

    标签item背景选中:bg_tabbar_record_selected@2x.png

    私有模块命名示例:

    首页搜索背景图:home_search@2x.png

    首页消息默认背景图:home_info_normal@2x.png

    首页消息高亮背景图:home_info_highlight@2x.png

    注释规范

    属性注释

    使用/** 注释 */的方式,这种方式在引用时Xcode会给出友好提示。

    @interface UserItem : BaseModel
    
    /** ID */
    @property(nonatomic,assign) NSInteger itemId;
    
    /** 用户名 */
    @property(nonatomic,strong) NSString *name;
    
    /** 密码 */
    @property(nonatomic,strong) NSString *password;
    
    /** 手机号 */
    @property(nonatomic,strong) NSString *phoneNum;
    
    /** 头像 */
    @property(nonatomic,strong) NSString *headerPic;
    
    /** 关注人ID */
    @property(nonatomic,assign) NSInteger attentionId;
    
    /** 热度 */
    @property(nonatomic,assign) NSInteger hotScore;
    
    /** 推荐状态 */
    @property(nonatomic,assign) NSInteger commendState;
    
    @end
    

    方法注释

    严格采用苹果官方提供的注释标准,这种方式在引用时Xcode会给出友好提示。

    /**
     对AF进行简单封装
     */
    @interface SSNetworkingManager : AFHTTPSessionManager
    
    /**
     单利方法
     @return 实例
     */
    +(instancetype _Nonnull )shareManager;
    
    /**
     *  封装的GET请求
     *
     *  @param URLString  请求的链接
     *  @param parameters 请求的参数
     *  @param success    请求成功回调
     *  @param failure    请求失败回调
     */
    - (void)SSGET:(NSString *)URLString parameters:(NSDictionary *)parameters success:(Success)success failure:(Failure)failure;
    
    /**
     *  封装的POST请求
     *
     *  @param URLString  请求的链接
     *  @param parameters 请求的参数
     *  @param success    请求成功回调
     *  @param failure    请求失败回调
     */
    - (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters success:(Success)success failure:(Failure)failure;
    
    /**
     *  封装POST图片上传(多张图片) // 可扩展成多个别的数据上传如:mp3等
     *
     *  @param URLString  请求的链接
     *  @param parameters 请求的参数
     *  @param picArray   存放图片模型(HDPicModle)的数组
     *  @param progress   进度的回调
     *  @param success    发送成功的回调
     *  @param failure    发送失败的回调
     */
    - (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters andPicArray:(NSArray *)picArray progress:(Progress)progress success:(Success)success failure:(Failure)failure;
    
    /**
     *  封装POST图片上传(单张图片) // 可扩展成单个别的数据上传如:mp3等
     *
     *  @param URLString  请求的链接
     *  @param parameters 请求的参数
     *  @param picModle   上传的图片模型
     *  @param progress   进度的回调
     *  @param success    发送成功的回调
     *  @param failure    发送失败的回调
     */
    - (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters andPic:(SSImageModel *)picModle progress:(Progress)progress success:(Success)success failure:(Failure)failure;
    
    /**
     *  封装POST上传url资源
     *
     *  @param URLString  请求的链接
     *  @param parameters 请求的参数
     *  @param picModle   上传的图片模型(资源的url地址)
     *  @param progress   进度的回调
     *  @param success    发送成功的回调
     *  @param failure    发送失败的回调
     */
    - (void)SSPOST:(NSString *)URLString parameters:(NSDictionary *)parameters andPicUrl:(SSImageModel *)picModle progress:(Progress)progress success:(Success)success failure:(Failure)failure;
    
    /**
     *  下载
     *
     *  @param URLString       请求的链接
     *  @param progress        进度的回调
     *  @param destination     返回URL的回调
     *  @param downLoadSuccess 发送成功的回调
     *  @param failure         发送失败的回调
     */
    - (NSURLSessionDownloadTask *)SSdownLoadWithURL:(NSString *)URLString progress:(Progress)progress destination:(Destination)destination downLoadSuccess:(DownLoadSuccess)downLoadSuccess failure:(Failure)failure;
    
    @end
    

    #pragma mark

    视图方法中必须添加mark标记,方便查找文件中的具体方法和理解整个类的结构。

     #pragma mark - Lifecycle
    
    -(id)init{}
    
     - (void)dealloc {}
    
     - (void)viewDidLoad {}
    
     - (void)viewWillAppear:(BOOL)animated {}
    
     - (void)didReceiveMemoryWarning {}
    
     #pragma mark - Lazy
    
      - (void)setUpTableView{}
    
     #pragma mark - IBAction
    
     - (IBAction)submitData:(id)sender {}
    
     #pragma mark - Common
    
     - (void)publicMethod {}
    
     - (void)privateMethod {}
    
     #pragma mark - UITextFieldDelegate
    
     #pragma mark - UITableViewDataSource
    
     #pragma mark - UITableViewDelegate
     
    

    编码规范

    判断nil或者YES/NO

    Preferred:

    if (someObject) { ... } 
    if (!someObject) { ... }
    

    Not preferred:

    if (someObject == YES) { ...} 
    if (someObject != nil) { ...}
    

    if (someObject == YES)容易误写成赋值语句, 自己给自己挖坑了...而且if (someObject)写法很简洁.

    条件赋值

    Preferred:

    result = object ? : [self createObject];
    

    Not preferred:

    result = object ? object : [self createObject];
    

    如果是存在就赋值本身, 那就可以这样简写.

    初始化方法

    Preferred:

    NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve"];
    NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal"};
    NSNumber *shouldUseLiterals = @YES;
    NSNumber *buildingZIPCode = @10018;
    

    使用字面量,保证代码更加简洁。

    定义属性

    Preferred:

    @property(nonatomic,assign) NSInteger itemId;
    @property(nonatomic,strong) NSString *name;
    

    BOOL赋值

    Preferred:

    BOOL isAdult = age > 18;
    

    Not preferred:

    BOOL isAdult;
    if (age > 18)
    {
        isAdult = YES;
    }
    else
    {
        isAdult = NO;
    }
    

    拒绝写死值

    Preferred:

    if (car == Car.Nissan) ...
    
    const int adultAge = 18; 
    if (age > adultAge) {
     ... 
    }
    
    

    Not preferred:

    if (carName == "Nissan") ...
    
    if (age > 18) { 
     ... 
    }
    

    死值每次修改的时候容易被遗忘, 地方多了找起来就悲剧了。而且定义成枚举或者static可以让错误发生在编译阶段。

    复杂的条件判断

    Preferred:

    if ([self canDeleteJob:job]) { ... }        
    
    - (BOOL)canDeleteJob:(Job *)job {
        BOOL invalidJobState = job.JobState == JobState.New
                              || job.JobState == JobState.Submitted
                              || job.JobState == JobState.Expired;
        BOOL invalidJob = job.JobTitle && job.JobTitle.length;
    
        return invalidJobState || invalidJob;
    }
    

    Not preferred:

    if (job.JobState == JobState.New
        || job.JobState == JobState.Submitted
        || job.JobState == JobState.Expired
        || (job.JobTitle && job.JobTitle.length)) {
     ... 
    }
    

    专门的方法做专门的事情。

    嵌套判断

    Preferred:

    if (!user.UserName) return NO;
    if (!user.Password) return NO;
    if (!user.Email) return NO;
    
    return YES;
    

    Not preferred:

    BOOL isValid = NO;
    if (user.UserName) {
        if (user.Password) {
            if (user.Email) isValid = YES;
        }
    }
    return isValid;
    

    黄金路径

    参数过多

    Preferred:

    - (void)registerUser(User *user) {
     ...
    }
    

    Not preferred:

    - (void)registerUserName:(NSString *)userName
                    password:(NSString *)password 
                       email:(NSString *)email {
     ...
    }
    

    当发现实现某一功能需要传递的参数太多时, 就预示着你应该聚合成一个model类了...这样代码更整洁, 也不容易因为参数太多导致出错。

    回调方法

    Preferred:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
    

    函数调用的可知性, 回调时被调用者要知道其调用者, 方便信息的传递, 所以建议在回调方法中第一个参数中加上调用者

    本文参考:
    http://www.jianshu.com/p/da8a471219d1
    http://www.jianshu.com/p/414bb5a53139

    相关文章

      网友评论

        本文标题:IOS编码规范

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