这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
引言
在我一开始写 Swift 代码时,总是显的不简洁,没有充分发挥 Swift 的特性。随着写的时间长了,也总结了一些 Swift 开发的小技巧,让代码看起来更加简洁和高大上。
内容一共分为两篇文章,我们先来看第一篇~
使用内置函数
现在有个整型数组,我们想计算数组内所有数字之和。第一反应可能就是 for 循环,于是就写出了下面的代码:
let numbers = [2021, 11, 12]
var sum = 0
for number in numbers {
sum += number
}
print(sum) //2044
当然,这么写也没啥毛病,但我们可以使用 reduce(_:_:)把 for 循环简化成一行:
let numbers = [2021, 11, 12]
let sum = numbers.reduce(0, +)
print(sum) //2044
上面这段代码就等价于 0 + 2021 + 11 + 12
reduce 的第一个参数 0 是初始值,相当于上面 for 循环代码中的 var sum = 0
第二个参数接受一个闭包,这就给了我们在闭包里为所欲为的机会了。
除了reduce(_:_:),Swift 还提供了其他的内置函数,比如filter(_:)、map(_:)、flatMap(_:)、firstIndex(where:)等等。更多的大家可以 command+shift+0 打开开发文档查看。
省略 return 关键字
如果一个函数或闭包只有一行代码,那就可以把 return 关键字省略掉。而且,如果你喜欢的话,可以把所有代码放在一行:
func makeGreeting(withName name: String) -> String {
"求点赞, \(name)"
}
func makeGreeting(withName name: String) -> String { "求点赞, \(name)" }
简化闭包
struct Person {
var name: String
var age: Int
...
}
假如有个 Persons 数组,里面是 Person 对象,现在要筛选出大于 18 岁的 Person,用前面提到的filter(_:),可以这么写:
let person1 = Person(name: "JieJie", age: 20)
let person2 = Person(name: "Faker", age: 25)
let person3 = Person(name: "JakeyLove", age: 30)
let person4 = Person(name: "JinX", age: 10)
let persons = [person1, person2, person3, person4]
let result = persons.filter { person in
person.age > 18
}
print(result.map{ $0.name }) //["JieJie", "Faker", "JakeyLove"]
Swift 自动为内联函数提供了参数名称缩写功能,所以上面的 filter 语句可以简化成:
let result = persons.filter{ $0.age > 18 }
检查数组是否越界
还是上面的 persons 数组,数量不固定,假如我们要对上面的 persons 数组抽奖,第 6 个人中奖,如果人数没有达到 6,那就延长抽奖日期,通常可能会这么做:
let index = 6
if index >= 0 && index < persons.count {
print("恭喜 \(persons[index].name) 中奖")
} else {
print("延长抽奖日期")
}
上面这个写法就显的很普通了,我们用数组的indices属性把它变得高大上:
if persons.indices.contains(index) {
print("恭喜 \(persons[index].name) 中奖")
} else {
print("延长抽奖日期")
}
默认值
大家都知道可以用??为可选变量设置默认值,其实在 Swift 中,还有更多的地方可以设置默认值,比如:
- 为函数参数设置默认值
- 为 dictionary 的某个 key 设置默认值
先来看看为函数参数设置默认值,设置后,该参数在调用时就可以省略:
func greet(name: String = "World") -> String {
"Hello,\(name)"
}
greet("World!!!") //Hello,World!!!
greet() //Hello,World
再来看看为 dictionary 的某个 key 设置默认值。
假如有个 names 数组,里面存放的是人名,现在要写个函数返回出现次数最多的人名。一种实现方式如下:
let names = ["小张", "小李", "小张", "小李", "小张", "小王"]
func findMostCountName(inNames names: [String]) -> String {
var occurrenceFor: [String : Int] = [:]
for name in names {
if let count = occurrenceFor[name] {
occurrenceFor[name] = count + 1
} else {
occurrenceFor[name] = 1
}
}
var maxCount = 0
var result = ""
for (name, count) in occurrenceFor {
if count > maxCount {
maxCount = count
result = name
}
}
return result
}
let name = findMostCountName(inNames: names)
print(name) //小张
再来看看给 dictionary:occurrenceFor 的 key 设置默认值的效果:
func findMostCountName(inNames names: [String]) -> String {
var occurrenceFor: [String : Int] = [:]
for name in names {
occurrenceFor[name, default: 0] += 1 //如果 key 存在,返回对应的 value;否则返回 0
}
var maxCount = 0
var result = ""
for (name, count) in occurrenceFor {
if count > maxCount {
maxCount = count
result = name
}
}
return result
}
可见,给 dictionary 键设置默认值可以使代码看起来更加整洁。只需一行代码,就可以替换掉 if-else 语句。
检查变量是否在两个数之间
假如有个字段:年龄,现在要判断它是不是在 18 岁到 32 岁之间。通常我们会这么做:
let age = 23
if age >= 18 && age <= 32 {
print("符合要求")
}
可能觉得像上面这么写没啥问题,但再来看看下面这个:
let age = 23
if age <= 18 && age >= 32 {
print("符合要求")
}
是不是很像,但这个时候 print 语句永远也不会执行。大家在读这两个 if 语句的时候有什么感受?是不是需要在大脑中有那么一下停顿,来思考符不符合条件。这就造成不易读而且容易出错。
在 Swift 中提供了更易读、简便的方法来实现:
let age = 23
if (18...32).contains(age) {
print("符合要求")
}
if (18...32) ~= age {
print("符合要求")
}
结语
- 尽量使用内置函数替代 for 循环
- 只有一行代码的函数省略 return 关键字
- 闭包的简化
- 检查数组越界的方法
- 为函数参数和字典的 key 提供默认值
- 检查变量是否在两个数之间
今天的小技巧就到这啦~ 大家觉得有用,不妨在项目中实践一下哦~