值
Object
结构同时只会有一个值存在:
优化前
class Object {
var name: Int?
var num: Int?
}
优化后
降低内存占用
- 枚举关联类型
的大小取决于最大的关联类型大小
逻辑更清晰
- 使用enum
相比大量使用if/else
逻辑更清晰
enum CustomType {
case name(String)
case num(Int)
}
减少var
属性
使用计算属性
使用计算属性
可以减少多个变量同步带来的潜在bug。
不推荐
class model {
var data: Object?
var loaded: Bool
}
model.data = Object()
loaded = false
推荐
class model {
var data: Object?
var loaded: Bool {
return data != nil
}
}
model.data = Object()
提示:计算属性因为每次都会重复计算,所以计算过程需要轻量避免带来性能问题。
控制流
使用filter/reduce/map
代替for
循环
使用filter/reduce/map
可以带来很多好处,包括更少的局部变量,减少模板代码,代码更加清晰,可读性更高。
不推荐
let nums = [1, 2, 3]
var result = []
for num in nums {
if num < 3 {
result.append(String(num))
}
}
// result = ["1", "2"]
推荐
let nums = [1, 2, 3]
let result = nums.filter { $0 < 3 }.map { String($0) }
// result = ["1", "2"]
使用guard
进行提前返回
推荐
guard !a else {
return
}
guard !b else {
return
}
// do
不推荐
if a {
if b {
// do
}
}
使用三元运算符?:
推荐
let b = true
let a = b ? 1 : 2
let c: Int?
let b = c ?? 1
不推荐
var a: Int?
if b {
a = 1
} else {
a = 2
}
使用for where
优化循环
for
循环添加where
语句,只有当where
条件满足时才会进入循环
不推荐
for item in collection {
if item.hasProperty {
// ...
}
}
推荐
for item in collection where item.hasProperty {
// item.hasProperty == true,才会进入循环
}
使用defer
defer
可以保证在函数退出前一定会执行。可以使用defer
中实现退出时一定会执行的操作例如资源释放
等避免遗漏。
func method() {
lock.lock()
defer {
lock.unlock()
// 会在method作用域结束的时候调用
}
// do
}
字符串
使用"""
在定义复杂
字符串时,使用多行字符串字面量
可以保持原有字符串的换行符号/引号等特殊字符,不需要使用``进行转义。
let quotation = """
The White Rabbit put on his spectacles. "Where shall I begin,
please your Majesty?" he asked.
"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""
提示:上面字符串中的""
和换行可以自动保留。
使用字符串插值
使用字符串插值可以提高代码可读性。
不推荐
let multiplier = 3
let message = String(multiplier) + "times 2.5 is" + String((Double(multiplier) * 2.5))
推荐
let multiplier = 3
let message = "(multiplier) times 2.5 is (Double(multiplier) * 2.5)"
集合
使用标准库提供的高阶函数
不推荐
var nums = []
nums.count == 0
nums[0]
推荐
var nums = []
nums.isEmpty
nums.first
访问控制
Swift
中默认访问控制级别为internal
。编码中应当尽可能减小属性
/方法
/类型
的访问控制级别隐藏内部实现。
提示:同时也有利于编译器进行优化。
使用private
/fileprivate
修饰私有属性
和方法
private let num = 1
class MyClass {
private var num: Int
}
使用private(set)
修饰外部只读/内部可读写属性
class MyClass {
private(set) var num = 1
}
let num = MyClass().num
MyClass().num = 2 // 会编译报错
函数
使用参数默认值
使用参数默认值
,可以使调用方传递更少
的参数。
不推荐
func test(a: Int, b: String?, c: Int?) {
}
test(1, nil, nil)
推荐
func test(a: Int, b: String? = nil, c: Int? = nil) {
}
test(1)
提示:相比ObjC
,参数默认值
也可以让我们定义更少的方法。
限制参数数量
当方法参数过多时考虑使用自定义类型
代替。
不推荐
func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {
}
推荐
struct Params {
let a, b, c, d, e, f: Int
}
func f(params: Params) {
}
使用@discardableResult
某些方法使用方并不一定会处理返回值,可以考虑添加@discardableResult
标识提示Xcode
允许不处理返回值不进行warning
提示。
// 上报方法使用方不关心是否成功
func report(id: String) -> Bool {}
@discardableResult func report2(id: String) -> Bool {}
report("1") // 编译器会警告
report2("1") // 不处理返回值编译器不会警告
元组
避免过长的元组
元组虽然具有类型信息,但是并不包含变量名
信息,使用方并不清晰知道变量的含义。所以当元组数量过多时考虑使用自定义类型
代替。
func test() -> (Int, Int, Int) {
}
let (a, b, c) = tes