据说你已经学习Swift几个月了,有没有想更进一步成为Swift高手的想法?我这里有11招秘技,各位施主且听我慢慢道来,结个善缘。javascript
任务: 求数字的平方。php
// 菜鸟版 func square(x: Int) -> Int { return x * x } var squaredOfFive = square(x: 5) square(x: squaredOfFive) // 625
为了求5的四次方咱们被迫建立变量 squaredOfFive — 高手可不喜欢被迫定义一个无用的变量。java
// 高手版 extension Int { var squared: Int { return self * self } } 5.squared // 25 5.squared.squared // 625
任务:打印输出数组内全部的元素。编程
// 菜鸟版 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) } }
任务:打印 5 次 陆家嘴安全
// 菜鸟版 var i = 0 while 5 > i { print("陆家嘴") i += 1 }
被迫定义了变量 i 来确保打印 陆家嘴 5 次。
注意定义越多的变量,越多的潜在风险,越多的生活问题。这就是蝴蝶效应,你难道想X生活不和谐?bash
// 高手版
for _ in 1...5 { print("陆家嘴") }
上面的代码实在是简洁,美妙。闭包
任务 : 让咱们写个欢迎新用户的程序。app
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”
任务:计算圆的直径
// 菜鸟版 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
如今半径和直径相互依赖,真实地反应了二者的关系。
记得上面说的蝴蝶效应吗? 越少的依赖,代码越简洁,问题越少,生活越美好!
任务:卖门票
// 菜鸟版 switch "Adult" { case "Adult": print("请付 50 元") case "Child": print("请付 25 元") case "Senior": print("请付 30 元") default: print("你确认不是僵尸吗,哥们?") }
“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绝不留情的指出来,合理利用集成开发环境是高手必备的。
任务: 用户选择微博主体颜色。
// 菜鸟版 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
任务: 获取偶数。
// 菜鸟版 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]
有没有感受函数式编程让你看起来聪明多了。
任务: 求两个数字的和。
// 菜鸟版 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
任务:计算圆的直径
// 菜鸟版 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赋值后调用。
任务: 一我的有多少根手指和脚趾
// 菜鸟版 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的方式被调用的。
任务: 定义一个包含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。
十二条技巧讲述完毕,打完收工。