iOS Swift 代码规范

编码格式

  1. 使用二元运算符(+, -,==, 或->)的前后都需要添加空格
let value = 1 + 2
  1. 在逗号后面加一个空格
let titleArray = [1, 2, 3, 4, 5]
  1. 方法的左大括号不要另起,并和方法名之间留有空格,注释空格
// function Define
func myFunction {
    // 处理
}
  1. 判断语句不用加括号
if typeValue == 1 {
    // 处理
}
  1. 尽量不使用self. 除非方法参数与属性同名
func setPerson(name: String, pAge: Int) {
    self.name = name
    age = pAge
}
  1. 在访问枚举类型时,使用更简洁的点语法
enum Direction {
    case north
    case south
    case east
    case west
}
let currentDirection = .west
  1. 添加有必要的注释,尽可能使用Xcode注释快捷键(⌘⌥/)
/// <#Description#>
///
/// - Parameters:
///   - tableView: <#tableView description#>
///   - section: <#section description#>
/// - Returns: <#return value description#>
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataList.count
}
  1. 使用 // MARK: -,按功能、协议、代理等分组
// MARK: - UITableViewDelegate

// MARK: - Action

// MARK: - Request
  1. 协议一致性:当对象要实现协议一致性时,推荐使用 extension 隔离协议中的方法集,这样让相关方法和协议集中在一起,方便归类和查找
// MARK: - UICollectionViewDelegate, UICollectionViewDataSource
extension XMHomeViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    // 代理方法
}

// MARK: - HttpsRequest
extension XMHomeViewController {
    // 网络请求方法
}
  1. 当对外接口不兼容时,使用@available(iOS x.0, *) 标明接口适配的起始系统版本号
@available(iOS 8.0, *)
func myFunction() {
    //
}

命名规范

  1. 常量,变量,函数,方法的命名规则使用小驼峰规则,首字母小写,类型名使用大驼峰规则,首字母大写。
class MyClass: class {
    let myImageView: UIImageView
    let myName: String
}
  1. 当命名里出现缩写词时,缩写词要么全部大写,要么全部小写,以首字母大小写为准
let htmlString = "https://www.baidu.com"
let urlString:  URLString
let userID:  UserID

class HTMLModel {
    //
}
  1. bool类型命名时,使用is作为前缀
var isMine: Bool = false
  1. Swift中类别(类,结构体)在编译时会把模块设置为默认的命名空间,所以不用为了区分类别而添加前缀,比如XYHomeViewController,但是为了和引用的第三方库作区分,建议可以继续使用前缀,以作为规范化处理,结构更清晰。

  2. 懒加载用来细致地控制对象的生命周期,这对于想实现延迟加载视图的UIViewController特别有用

// MARK: - 懒加载
private lazy var tableView: UITableView = {
    let tableView = UITableView.init(frame: CGRect.zero, style: .plain)
    tableView.separatorStyle = .none
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 200
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(UINib(nibName: homeListCell, bundle: nil), forCellReuseIdentifier: homeListCell)
    return tableView
}()
  1. 当函数的第一个参数构成整个语句的介词时(如,at, by, for, in, to, with 等),为第一个参数添加介词参数标签
func login(with username: String?, password: String?) {
    //
}

语法规范

  1. 可选类型拆包取值时,使用if let 判断
if let data = result.data {
    //
}
  1. 多个可选类型拆包取值时,将多个if let 判断合并
if let name = person.name, let age = person.age {
    //
}
  1. 尽量不要使用 as! 或 try!,对于可选类型Optional多使用as?,?? 可以给变量设置默认值
// 使用if let as?判断
if let name = person.name as? String {
    //
}
// 给name变量设置默认值
var name = person.name ?? ""
  1. 类型推断:推荐用紧凑方式写代码,让编辑器推断实例中常量和变量的类型。类型推断也适用于小型非空数组/字典。如有需要,请指定特定类型,例如:CGFloat或者Int16等。
// 推荐写法
let message = "Click the button"
let currentBounds = computeViewBounds()
var names = ["Mic", "Sam", "Christine"]
let maximumWidth: CGFloat = 106.5
// 不推荐写法
let message: String = "Click the button"
let currentBounds: CGRect = computeViewBounds()
var names: [String] = ["Mic", "Sam", "Christine"]

针对空数组和空字典的类型推断写法,推荐使用类型注释。此准则也意味着选择描述性名称比以前更加重要。

// 推荐写法
var names: [String] = []
var lookup: [String: Int] = [:]
// 不推荐写法
var names = [String]()
var lookup = [String: Int]()
  1. 常量定义,建议尽可能定义在类型里面,避免污染全局命名空间,如果是其他地方有可能复用的cell可以定义在类型外面
static let homeListCell = "HomeListCell"

class HomeListCell: UITableViewCell {
    static let kHomeCellHeight = 80.0
    //
}
  1. 当方法最后一个参数是Closure类型,调用时建议使用尾随闭包语法
UIView.animateWithDuration(1.0) {
     self.myView.alpha=0
}
  1. 最短路径规则:当编码遇到条件判断时,左边的距离是黄金路径或幸福路径,因为路径越短,速度越快。guard 就为此而生的。
func login(with username: String?, password: String?) throws -> LoginError {
  guard let username = username else { 
    throw .noUsername 
  }
  guard let password = password else { 
    throw .noPassword
  }
  // 处理登录
}
  1. 循环遍历使用for-in表达式
// 循环
for _ in 0..<list.count {
  print("items")
}
// 遍历
for(index, person) in personList.enumerate() {
    print("\(person)is at position #\(index)")
}
// 间隔2位循环
for index in 0.stride(from: 0, to: items.count, by: 2) {
  print(index)
}
// 翻转
for index in (0...3).reversed() {
    print(index)
}

Swift4.2新特性

  1. CaseIterable协议:定义的枚举遵循CaseIterable协议后,编译时Swift 会自动合成一个allCases属性,是包含枚举的所有case项的数组
enum NetState: CaseIterable {
    case wifi
    case hotWifi
    case mobile
    case none
}
for item in NetState.allCases {
    print(item)
}
  1. warning 主要用于标记一些工作还没有完成或者需要完善,Xcode 会发出一个警告;#error 标记错误,Xcode 会发出一个编译错误这样你的代码就完全不能编译

#warning("列表刷新需要优化")

#if os(macOS)
#error("MyLibrary is not supported on macOS.")
#endif
  1. 新增 allSatisfy():一种检查序列中的所有元素是否满足条件的新方法
// 判断数组的所有元素是否全部大于80
let scores = [86, 88, 95, 92]
// 返回一个BOOL
let passed = scores.allSatisfy({ $0 > 80 })
print(passed)
// 输出:true
  1. 新增 last(where:) 和 lastIndex(where:) 方法来获取数组中满足条件的最后的元素和索引值
let a = [10, 20, 30, 40, 50, 30, 20]
// 获取满足条件的元素
print(a.last(where: { $0 > 30 }))   //50
// 获取满足条件的元素的索引
print(a.lastIndex(where: { $0 > 25 }))   //4
  1. 新增 random() 随机数方法来生成一个随机数, 只需提供一个随机数范围即可
// 随机数
let ranInt = Int.random(in: 0..<10)
let ranFloat = Float.random(in: 0..<10)

let a = [10, 20, 30, 40, 50, 30, 20]
// 对数组重新洗牌, 重新随机排序返回一个数组
let shuffled = a.shuffled()
// 获取数组中的一个随机元素,空数组返回nil
let random = a.randomElement() 
  1. 新增 removeAll(where:) 方法,高效地执行根据条件删除操作
var names = ["John", "Michael", "Graham", "Andy", "Eric", "Andy"]
names.removeAll { $0.hasPrefix("Andy") }
print(names)
// 输出:["John", "Michael", "Graham", "Eric"]

Swift5新特性

  1. ABI(Application Binary Interface)稳定:ABI定义了函数如何调用,数据如何在内存中呈现,元数据在哪里,以及如何访问等底层交互。之前的Swift版本中ABI还没稳定,所以每一个APP,都自己包含它Swift版本所对应的Swift Dynamic Library。ABI稳定之后,Swift动态库将包含在iOS操作系统里,它将兼容每一个Swift版本。

  2. 新增 @dynamicCallable 为Swift添加了一个新属性,允许使用一个简单的语法糖像调用函数一样调用命名类型,需要实现下面两个方法中的一个

func dynamicallyCall(withArguments args: [Int]) -> Double
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double

// 定义方式
@dynamicCallable
struct RandomNumberGenerator {
    func dynamicallyCall(withArguments args: [Int]) -> Double {
        let numberOfZeroes = Double(args.first ?? 0)
        let maximum = pow(10, numberOfZeroes)
        return Double.random(in: 0...maximum)
    }
}
// 调用方式
let random = RandomNumberGenerator()
let num = random(2)
// random(2)等同于random.dynamicallyCall(withArguments: [2])
  1. 修改:定义一个带有(可变参数 => 数组参数)的枚举
enum X {
    case foo(bar: [Int]) 
} 
func baz() -> X {
    return .foo(bar: [0, 1, 2, 3]) 
} 
  1. 新增创建原始字符串的功能,以及创建多行字符串
let quote = "Alice: \"How long is forever?\" White Rabbit: \"Sometimes, just one second.\""
let rain = #"The "rain" in "Spain" falls mainly on the Spaniards."#
let multiline = #"""
    The answer to life,
    and everything is \#(answer).
    """#
  1. Swift 5中无论有多少个嵌套的可选,最后返回值永远只是一个可选值,使用try?
// 类型: let messages: String?
let messages = try? user?.getMessages()
print(messages ?? "")
  1. 新增了一个函数 count(where:),可以获取数组中符合条件的元素的个数
let arr = [1, 28, 3, 40, 5, 6]
let count = arr.count(where: { $0 > 10 })
print(count)  // 2
  1. 在 Swift4.x 的版本中有两个函数 compactMap 和 mapValues
    compactMap: 返回一个操作后得到的新的数组, 类似flatMap
    mapValues: 对字典的value值执行操作, 返回改变value后的新的字典
    Swift5.0 新增了一个函数 compactMapValues 返回一个对value操作后的新字典, 并且自动过滤不符合条件的键值对
let guys = [
    "Hudson": "30",
    "Clarke": "40",
    "Robinson": "50",
    "Hartis": "DNF"
]
let comMap = guys.compactMapValues({ Int($0) + 3 })
print(comMap)
// ["Clarke": 43, "Robinson": 53, "Hudson": 33]

参考文献
https://blog.csdn.net/liushuo19920327/article/details/79121384

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271