Swift 小技巧

1. 扩展(Extension)

任务: 求数字的平方。

// 对比写法
func square(x: Int) -> Int { return x * x }
var squaredOfFive = square(x: 5)
square(x: squaredOfFive) // 625

为了求5的四次方我们创建变量 squaredOfFive 

// 改良写法
extension Int { 
 var squared: Int { return self * self }
}
5.squared // 25
5.squared.squared // 625

2. 泛型(Generics)

任务:打印输出数组内所有的元素。

// 对比写法
var stringArray = ["金庸", "古龙", "梁羽生"]
var intArray = [1, 3, 4, 5, 6]
var doubleArray = [1.0, 2.0, 3.0]
func printStringArray(a: [String]) { 
        for s in a { 
              print(s) 
        }
}
func printIntArray(a: [Int]) { for i in a { print(i) } }
func printDoubleArray(a: [Double]) {for d in a { print(d) } }

简化这些步骤

// 改良写法
func printElementFromArray<T>(a: [T]) {
        for element in a { 
            print(element) 
        } 
}

3. For 遍历 vs While 遍历

任务:打印 5 次 

// 对比写法
var i = 0
while 5 > i {
      print("xxx")
      i += 1 
}

对比

// 改良写法
for _ in 1...5 { 
     print("xxx") 
}

4. Gaurd let vs if let

任务 : 写个欢迎新用户的程序。

var myUsername: Double?
var myPassword: Double?
// 对比写法
func userLogIn() {
     if let username = myUsername {
          if let password = myPassword {
               print("欢迎, \(username)"!)
          }
     }
}

去掉嵌套函数

// 改良写法
func userLogIn() {
     guard let username = myUsername, let password = myPassword 
          else { return } 
        print("欢迎, \(username)!") 
}

注意这里如果myUsername 或 myPassword nil,都会提前结束,否则就会打印 “欢迎, XXX”

5. 计算属性 vs 函数

任务:计算圆的直径

// 对比写法
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

关联的数据可以这样做

// 改良写法
var radius: Double = 10
var diameter: Double {
      get { return radius * 2}
      set { radius = newValue / 2} 
}
radius // 10
diameter // 20
diameter = 1000
radius // 500

现在半径和直径相互依赖,真实地反应了两者的关系。

6. 枚举 - 类型安全

任务:卖门票

// 对比写法
switch "Adult" {
   case "Adult": print("请付 50 元")
   case "Child": print("请付 25 元")
   case "Senior": print("请付 30 元")
   default: print("xxx") 
}

“Adult”, “Child”, “Senior” 这里都是硬编码,每次需要输入手动输入这些字符, 手动键入越少,错误越少。

// 改良写法
enum People { case adult, child, senior }
switch People.adult {
   case .adult: print("请付 50 元")
   case .child: print("请付 25 元")
   case .senior: print("请付 30 元")
   default: print("你确认不是僵尸吗,哥们?") 
}

这样就避免了不小心输入错误的问题,因为 “.adult”, “.child”, “.senior” 被定义成了enum', 任何不在预定义范围内的实例都会被Xcode指出来

7. 空合运算符

任务: 用户选择微博主体颜色。

// 对比写法
var userChosenColor: String? 
var defaultColor = "Red"
var colorToUse = ""
if let Color = userChosenColor { 
     colorToUse = Color 
} else { 
     colorToUse = defaultColor
 }

优化

// 改良写法
var colorToUse = userChosenColor ?? defaultColor

 如 userChosenColor 为 nil, 则选择 defaultColor, 否则则userChosenColor.
空合运算符是对以下代码的简短表达方法。

a != nil ? a! : b

8. 函数式编程

任务: 获取偶数。

// 对比写法
var newEvens = [Int]()
for i in 1...10 {
  if i % 2 == 0 { 
      newEvens.append(i) 
    } 
}
print(newEvens) // [2, 4, 6, 8, 10]

简化

// 改良写法
var evens = (1...10).filter { $0 % 2 == 0 } 
print(evens) 
// [2, 4, 6, 8, 10]

9. 闭包 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 }
sumUsingClosure(5, 6) // 11 

10. 属性观测器

任务:计算圆的直径

// 对比写法
var radius = 10.0
func getDiameter(radius: Double) -> Double { 
      return radius * 2
}

getDiameter(radius: radius) // return 20

这里不需要专门定义函数。

// 改良写法
var diameter = 0
var radius: Double = 10 {
      willSet { print("准备赋值中") }
      didSet { diameter =radius * 2}
     }
}
radius  = 10 // 准备赋值中
diameter // 20.0

willSet 会在给变量radius赋值前调用,而 didSet 会在给变量radius赋值后调用。

11.便利初始化

任务: 一个人有多少根手指和脚趾

// 对比写法
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的方式被调用的。

12. 延迟初始化

任务: 定义一个包含pi常量作为属性的类。

// 对比写法
class MathHelper {
var pi: Double = {
    // 计算pi
    return resultOfCalculation
    }()

}

计算pi的工作量是繁重的,且对于调用者不是必须的,可以假想下MathHelper内包含数十个类pi常量的场景,如果不在使用的时候再初始化常量会浪费多少宝贵的计算资源。

// 改良写法
class MathHelper {

lazy var pi: Double = {
      // 计算pi
    return resultOfCalculation
    }()

}

lazy 一方面可以让初始化成本较高的变量延迟初始化,提高资源利用效率。另一方面可以延迟初始化具有外部依赖的属性变量。

class Person {
var name: String
lazy var personalizedGreeting: String = {
    [unowned self] in
    return "Hello, \(self.name)!"
    }()

init(name: String) {
        self.name = name
    }
}

上面的例子中,属性personalizedGreeting依赖于变量name。

或许很多技巧你已经了解了,也许有更多没有被提到的更方便的技巧,欢迎留言探讨。

猜你喜欢

转载自blog.csdn.net/weixin_40287666/article/details/81147096