Swift: 小技巧

Swift: 小技巧_第1张图片
swift.jpg
  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
  1. 泛型(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(a: [T]) {
        for element in a { 
            print(element) 
        } 
}
  1. For 遍历 vs While 遍历
    任务:打印6次Swift
// 菜鸟版
var i = 0
while 5 > i {
      print("Swift")
      i += 1 
}

被迫定义了变量 i 来确保打印 Swift 5 次。
注意!!!定义越多的变量,越多的潜在风险,越多的生活问题。这就是蝴蝶效应,你难道想X生活不和谐?

// 高手版
for _ in 1...5 { 
     print("Swift") 
}

上面的代码实在是简洁,美妙。

  1. 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,走{return}都会提前结束,否则才会打印 “欢迎, XXX”

  1. 计算属性 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

上面我们创建了2个毫无关系的函数,可是直径和周长两者真的没有关系吗?

// 高手版 
var radius: Double = 10 
var diameter: Double { 
    get { return radius * 2} 
    set { radius = newValue / 2} 
} 
radius // 10 
diameter // 20 
diameter = 1000 
radius // 500

现在半径和直径相互依赖,真实地反应了两者的关系。
记得上面说的蝴蝶效应吗? 越少的依赖,代码越简洁,问题越少,生活越美好!

  1. 枚举 - 类型安全
    任务:卖门票
// 菜鸟版 
switch "Adult" { 
    case "Adult": print("请付 50 元") 
    case "Child": print("请付 25 元") 
    case "Senior": print("请付 30 元") 
    default: print("wtf?") 
}

“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("wtf?") 
}

这样你就避免了不小心输入错误的问题,因为 “.adult”, “.child”, “.senior” 被定义成了enum', 任何不在预定义范围内的实例都会被Xcode毫不留情的指出来,合理利用集成开发环境是高手必备的。

  1. 空合运算符
    任务: 用户选择微博主体颜色。
// 菜鸟版 
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
  1. 函数式编程
    任务: 获取偶数。
// 菜鸟版
var newEvens = [Int]()
for i in 1...10 {
  if i % 2 == 0 { 
      newEvens.append(i) 
    } 
}
print(newEvens) // [2, 4, 6, 8, 10]

这种for循环真是冗长,让人看的昏昏欲睡。

// 高手版
var evens = (1...10).filter { $0 % 2 == 0 } 
print(evens) 
// [2, 4, 6, 8, 10]

有没有感觉函数式编程让你看起来聪明多了。

  1. 闭包 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
  1. 属性观测器
    任务:计算圆的直径
// 菜鸟版
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的方式被调用的。

  1. 延迟初始化
    任务: 定义一个包含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。

你可能感兴趣的:(Swift: 小技巧)