当前位置: 首页>后端>正文

iOS 编程规范

开发规范的目的是保证统一项目成员的编码风格,并使代码美观,希望该份规范能给大家起到借鉴作用。

1. 项目简介

采用 MVC 框架开发,开发语言为 Swift。

2. 项目结构

2.1 工程目录

  • SupportingFiles(包含 AppDelegate、Assets、Info.plist等工程入口及配置文件)
  • Utils(工具类,Extension<扩展可以按类放在不同文件夹内>、各类 Manager 工具等)
  • Classes(类文件主目录,包含 App 内所有功能模块)
  • Components (自定义控件)
  • Base(基类,包含一些定制化的内容,例如页面样式)
  • ThirdPart(第三方的类库和对第三方封装,比如第三方登录、支付、IM等
  • LocalResource (图片、音频、视频等资源文件)
  • CoreData(数据库相关的表)

<strong>注:项目全部采用实体文件夹,不要在项目中新建 New Group 虚拟文件夹</strong>

2.2 MVC 业务逻辑

说明
controller 1.处理页面展示逻辑,提示框封装在基类 BaseViewController 中
2.页面跳转必须在 controller 中进行,不要直接放在 view 中
3.当 UITableView 或者 UICollectionView 的 dataSource 包含较多代码时,可以为该 controller 新建一个 dataSource 类
viewModel 1.逻辑计算(如订单支付页面, 应收金额计算的计算逻辑)
2.网络请求,JSON数据 → 数据模型(SwiftyJSON 解析)
handler 将 contoller 的部分业务逻辑抽离到该类中,例如 AlertController 弹出、权限授权检测等等,目的是为了保证 controller 代码整洁, 避免过度臃肿,不利于后期维护
view 对页面相关联的 view 进行封装,不要在 controller 中直接添加单个控件
model 数据模型,项目中数据传递建议使用解析后的 model, 不要直接传递 Json,不利于代码阅读及理解

3. 代码结构

controller 中的代码使用 // MARK: -- <#注释#> -- 标记进行分段,便于代码快速查找

// MARK: -- Life Cycle --
// MARK: -- Delegate --
// MARK: -- Private Methods --
// MARK: -- Event Resopnse --
// MARK: -- Other --

4. 命名规则

  • 类名、Protocol、结构体和枚举加上前缀 —— “Hex”
  • 全局常量命名使用 k 前缀 + UpperCamelCase 命名

4.1 类、结构体

controller、Struct、enum 采用大驼峰(UpperCamelCase)命名方式, 目录结构可以采用图示

4.2 成员变量、属性

  • 采用驼峰式命名(lowerCamelCase),并使用完整的单词
  • 不建议使用 tempArr、array1、dic1 之类的命名

正确示例:userName、birthdayImg、subtitleLabel

注:1.只读属性可以添加修饰 private(set) 2.不对外公开的属性, 可以添加修饰 private 例如: class Person { private(set) var name: String}

4.3 方法名

  • 以小写字母开头,每一个后续的单词首字母大写,使用完整的单词
  • 方法名不要随意命名, 命名要精简且语义清晰(可读性高),不能为了精简牺牲可读性

4.4 图标文件命名规则

图标命名规则采用单词小写加下划线的方式命名,前缀统一为icon_,对应大小的图标名称后加上@1x、@2x、@3x后缀,表明该图标对应几倍图

资源类型 前缀 示例
图标 icon_ icon_star@2x
功能引导 icon_guide icon_guide_first@2x
标签图标 icon_tabbar icon_tabbar_homepage@2x
分享类 icon_share icon_share_qq@2x

按钮不同状态命名规则

资源类型 后缀 示例
正常 _normal icon_searchBtn_normal@2x
高亮 _highlighted icon_searchBtn_highlighted@2x
不可用 _disabled icon_searchBtn_disabled@2x
选中 _selected icon_searchBtn_selected@2x

4.5 控件命名规则

控件类型 后缀(控件全称) 示例
UITextView TextView contentTextView
UITextField TextField titleTextField
UILabel Label subtitleLabel
UIButton Button searchButton
UIImageView ImageView sexImageView
UISlider Slider progressSlider
UISwitch Swith msgPushSwitch

5.代码格式化

5.1 空格

方法参数与类型注释、多个参数之间、返回值类型之间需要添加空格

// Bad
func functionName(paraA:Int,paraB:String)-><#return type#> {
    <#function body#>
}

// OK
func functionName(paraA: Int, paraB: String) -> <#return type#> {
    <#function body#>
}

变量名与类型注释之间、赋值号左右需要添加空格

// Bad
var value:Type=defaultValue

// OK
var value: Type = defaultValue

类继承,遵循接协议等,冒号前面不加空格, 但后面跟空格,如遵循多个协议, 以英文逗号隔开, 逗号前面不加空格, 但后面要加

class Student: Person, Sendable, Codable {
    func doSomething() {}
}

关系运算符(如 >=、!=)和逻辑运算符(如 &&、||)两边要有空格

// OK
(someValue > 100) true : false

// OK
(items) ?: []

5.2 花括号

func functionName(value: Int) {
                   ↑空格,此处花括号不用换行
    if value == 10 {
   空格↑           ↑空格,花括号不要另起一行
    } else if value >= 100 {
  空格↑                    ↑空格,花括号不要另起一行
    } else {
        花括号不要另起一行
    }
}

5.3 换行符

当方法参数为三个及三个以上时,参数可以另起一行,

private func updateLogTaskStatus(_ logTask: UpLoadLogTask,
                                 _ status: HexUpLoadLogTaskStaus,
                                 _ objectName: String,
                                 context: NSManagedObjectContext) {
    
}

定义数组或字典中包含多个元素时, 每个元素可以另起一行

let para = ["partnerId": HexTokenModel.partnerID,
               "partnerName": HexTokenModel.partnerName,
               "storeId": HexTokenModel.storeId,
               "storeName": HexTokenModel.storeName,
               "posId": HexTokenModel.posId,
                "uploadDate": Date.getYMDDateStr(timeIntervalSince1970: Date().timeIntervalSince1970),
                "ossObjectName": objcName,
                "logType": logType]

6.代码注释

清晰的代码注释更有益于代码阅读、后期代码维护、bug修复。

  • 定义的属性、方法等,采用快捷键 Command + Option + / 进行标注

例如:

// MARK: -- 渠道信息 --
struct HexOrderProductChannelModel: HandyJSON {
    /// 来源 区分是POS系统产生或被推送进入
    var source: String?
    /// 设备类型 POS系统内部的设备类型,比如PAD或者KIOSK
    var deviceType: String?
    /// 订单类型 区分堂食、外带和外送
    var orderType: HexOrderProductChannelOrderType?
    /// 配送方式 区分是预约单还是实时单
    var deliveryType: String?
    /// 渠道名 第三方平台名称,比如小程序,美团和饿了么
    var tpName: String?
    /// 编码 渠道编码,后台配置的业务编码
    var code: String?
}
/// 获取当前营业日前几个营业日的日期, 例如当前营业日是 2022-09-06
/// - Parameter days: 例如获取近3个营业日, days = -3, 负数表示当前日期往前算, 正数表示从当前日期往后数
/// - Returns: 例如: [2022-09-05, 2022-09-04, 2022-09-03]
private mutating func businessDates(since days: Int) -> [String] {
    var dates: [String] = []
    guard let currentBusinessDate = self.dateFormatter.date(from: HexTokenModel.busDate) else { return dates }
    let isEarlier = days < 0
    for i in 1...abs(days) {
        if let date = currentBusinessDate.dateByAddingDays(isEarlier (i * -1) : i) {
            dates.append(self.dateFormatter.string(from: date))
        }
    }
    return dates
}
  • <strong>若某部分功能逻辑处理较复杂,关键部分代码请写出相应实现逻辑,便于其他同事更快速理解业务流程</strong>

7. 其他

  1. 对于工程内引用的第三方库,建议进行二次封装,便于后期做迁移
  2. 函数参数最多不得超过 8 个;寄存器数目问题,超过 8 个会影响效率
  3. 图形化的字面量,#colorLiteral(...), #imageLiteral(...)禁止在项目工程中使用
  4. 避免强制解包以及强制类型映射,尽量使用if let 或 guard let进行解包,禁止try!形式处理异常,避免使用隐式解包
  5. 使用 guard 来提前结束条件,避免形成判断嵌套;
  6. 类似注解的修饰词单独占一行,如@objcMembers,@propertyWrapper, @discardableResult 等
  7. 在闭包中使用 self 时使用捕获列表[weak self]避免循环引用,闭包开始判断 self 的有效性
  8. 使用委托和协议时,避免循环引用,定义属性的时候使用 weak 修饰
  9. 表示单例的静态属性,一般命名为 shared 或者 default
  10. 尽量消除 warning

https://www.xamrdz.com/backend/35s1938425.html

相关文章: