引言
从OC转到Swift已经有接近半年了,但是很多地方都是用的最笨最基础的写法来完成,虽然代码没问题,功能能实现,不过对于想提升自己的你来说,还是得找个途径来优化自己的代码,自己维护也轻松,别人看着也舒适。正所谓不积跬步无以至千里,自己也正在一点一滴的积累,在网上看着大神们的写法,敲一遍不代码记得住,所以根据别人的文章,自己来整理并且记录知识。
1.扩展
要求: 求数字的平方
// 基础写法
func square(x:Int) -> Int {return x * x}
var squaredNum = square(x: 5)
square(x: squaredNum)
这种写法虽然也可以完成,但是如果需要求5的4次方,就得创建一个变量,或者square(x: square(x: 5))
来完成,这里可以使用扩展,链式的完成这个需求
// 高手写法
extension Int {
var squared:Int { return self * self}
}
5.squared // 5的平方,25
5.squared.squared // 5的4次方,625
2. 泛型
要求:打印输出3个数组内的所有元素
// 基础写法
let stringArr = ["字符串1","字符串2","字符串3"]
let intArr = [1,2,3]
let doubleArr = [1.0,2.0,3.0]
func printStringArray(arr:[String]) {
for str in arr {
print(str)
}
}
func printIntArray(arr:[Int]) {
for i in arr {
print(i)
}
}
func printDoubleArray(arr:[Double]) {
for i in arr {
print(i)
}
}
就为了输出三个数组,就得写三个方法,那要是数组种类多了怎么办,不能忍啊
// 高手写法
func printElemtFromArray<T>(arr: [T]) {
for elemt in arr {
print(elemt)
}
}
3. Gaurd let if let
要求:写个欢迎新用户的程序
// 基础写法
var myUserName: String?
var myPassword: String?
func userLogin() {
if let userName = myUserName {
if let password = myPassword {
print("欢迎用户\(userName)")
}
}
}
在程序里面嵌套代码太多也是挺讨厌的,能不写就不写吧
// 高手写法
func userLogin() {
guard let userName = myUserName,let password = myPassword else {
return // myUserName,myPassword为空时
}
print(userName,password)
}
4. 属性观测器
要求:计算圆的直径
// 基础版本
func getDiameter(radius: Double) -> Double { return radius * 2}
func getRadius(diameter: Double) -> Double { return diameter / 2}
getDiameter(radius: 10) // return 20
getRadius(diameter: 200) // return 100
getRadius(diameter: 600) // return 300
在上面我们创建了2个毫无关系的函数,可是直径和周长真的没关系吗?
// 高手写法
var diameter:Double = 0
var radius:Double = 10 {
willSet { print("装备赋值中") }
didSet { diameter = radius * 2 }
}
willSet 会在给变量radius赋值前调用,而 didSet 会在给变量radius赋值后调用。
5. 空合运算符
要求:用户选择微博主题颜色
// 基础写法
var userChoseColor:String?
var defaultColor = "red"
var colorToUse = ""
if let theColor = userChoseColor {
colorToUse = theColor
}else {
colorToUse = defaultColor
}
这确实有些臃肿,来减减肥
// 高手写法
colorToUse = userChoseColor ?? defaultColor
稍微解释下,如userChoseColor为nil,则会选择defaultColor,否则为userChoseColor。其实空合运算符就是对一下代码的简短表达方法。
a != nil ? a! : b //三目运算符
6. 函数式编程
要求:获取偶数
// 基础写法
let evensArr:Array<Int> = [1,2,3,4,5,6,7,8,9,10]
var newEvensArr:Array<Int> = Array()
for i in 0..<evensArr.count {
if i % 2 == 0 {
newEvensArr.append(i)
}
}
print(newEvensArr)
这种for循环真是冗长,看着就昏昏欲睡
// 高手写法
let newEvensArr = evensArr.filter({$0 % 2 == 0})
print(newEvensArr)
这里涉及到三种高阶函数,map,filter,reduce,以及$的含义,详情见文章《Swift 的 Map、Filter、Reduce等高阶函数,以及$的含义》
7. 闭包 vs 函数
要求:求两个数字的和
// 基础写法
func sum(x: Int, y: Int) -> Int {
return x + y
}
var result = sum(x: 5, y: 6) // 11
为了这个功能我们还需要记住函数名称? 就不能直接调用属性得到值吗?当然可以
// 高手写法
var sumUsingClosure:(Int,Int) -> Int = { $0 + $1 } // 用闭包替代函数
print(sumUsingClosure(9,1)) // 10
8. 遍历初始化
要求:一个人有多少根手指和脚趾
// 基础写法
class Human {
var finger:Int
var toe:Int
init(finger:Int,toe:Int) {
self.finger = finger
self.toe = toe
}
}
var daDi = Human(finger: 10, toe: 10)
daDi.finger // 10
daDi.toe // 10
因为绝大部分的人都有十根手指和脚趾,可以初始化时预先赋值
class Human {
var finger:Int
var toe:Int
init(finger:Int,toe:Int) {
self.finger = finger
self.toe = toe
}
convenience init() {
self.init(finger: 10, toe: 10)
}
}
var daDi = Human()
daDi.finger // 10
daDi.toe // 10
Swift中可以在init初始化方法前加上convenience关键字,这类方法主要提供使用上的方便。
所有的convenience 初始化方法,都必须调用同一个类中的顶级初始化方法完成初始化。另外convenience的初始化方法,是不能被子类重写或从子类中以super的方式被调用的。
9. 延迟初始化(懒加载)
要求:定义一个包含pi常量作为属性的类。
\\ 基础写法
class MathHelper {
var pi:Double = {
// 计算pi
return resultOfCalculation
}()
}
计算pi的工作量是繁重的,且对于调用者不是必须的,可以假想下MathHelper内包含数十个类pi常量的场景,如果不在使用的时候再初始化常量会浪费多少宝贵的计算资源。
class MathHelper {
lazy var pi:Double = {
// 计算pi
return resultOfCalculation
}()
}
简单来说,就是在使用时再去加载,不使用时不会进行计算、加载
lazy 一方面可以让初始化成本较高的变量延迟初始化,提高资源利用效率。另一方面可以延迟初始化具有外部依赖的属性变量。