Swifter - 100 个 Swift 必备 tips

Swifter - 100 个 Swift 必备 tips,作者[王巍](SWifter - 100个 Swift 必备 tips)。书买了很久了,25元比实体书便宜不少,而且收入基本上都归作者。学习完疯狂 Swift 讲义,再看看这个补充一下。

章节顺序可能与书不一致,全凭兴趣随意浏览,尤其是不太懂得方面。

##操作符
infix 表示一个中位操作符,前后都有输入。类似的还有 prefix 和 postfix。

associativity 定义了结合律

precedence 运算的优先级,Swift 中乘法和除法的优先级是150,加法和减法是140,这里定义160,就是高于普通的四则运算。

操作符定义在全局,不可滥用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//  main.swift
// Swift-test

import Foundation

struct Vector2D {
var x = 0.0
var y = 0.0
}

func +(left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}

let v1 = Vector2D(x: 2.0, y: 3.0)
let v2 = Vector2D(x: 1.0, y: 5.0)
print(v1 + v2) // Swift_test.Vector2D(x: 3.0, y: 8.0)

infix operator +* {
associativity none
precedence 160
}

func +*(left: Vector2D, right: Vector2D) -> Double {
return left.x * right.x + left.y * right.y
}

print(v1 +* v2) // 17.0

随机数生成

创建一个 Range 的随机数的方法,方便以后复用。

Swift 支持 // MARK: 、// TODO:、// FIXME:等编译标记,方便分段,将一标签的形式显示在导航栏中,让程序更易读。

1
2
3
4
5
6
7
8
9
10
// MARK: 实现方法
func randomInRange(range: Range<Int>) -> Int {
let count = UInt32(range.endIndex - range.startIndex)
return Int(arc4random_uniform(count)) + range.startIndex
}

// TODO: 测试是否有效
for _ in 0...100 {
print(randomInRange(1...6))
}

断言

对于判断输入是否满足某种条件的运用情景,使用断言比 if 更合适。且在 Debug 编译是才有效,运行时不被编译执行,不会消耗运行时的性能。是非常合适的调试判断。

1
2
3
4
5
6
7
8
9
10
import Foundation

func convertToKelvin( celsius: Double) -> Double {
let AbsoluteZeroInCelsius = -273.15
assert(celsius > AbsoluteZeroInCelsius, "输入的摄氏温度不能低于绝对零度。")
return celsius - AbsoluteZeroInCelsius
}

let roomTemperature = convertToKelvin(27)
print(roomTemperature) // 300.15

自省

程序设计和人类哲学所面临的同一个重大课程就是解决“我是谁”。

isKindOfClass、isMemberOfClass、is

1
2
3
4
5
6
7
8
9
class ClassA: NSObject { }
class ClassB: NSObject { }

let obj1: NSObject = ClassA()
let obj2: NSObject = ClassB()

print(obj1.isKindOfClass(ClassA.self)) // true
print(obj2.isMemberOfClass(ClassA.self)) // false

属性观察

属性观察可以对当前类型内监视其属性的设定,并作出响应。

1
2
3
4
5
6
class MyClass {
    var date: NSDate {
        willSet {
        print("即将将日期从 \(date) 设定至 \(newValue)")
        }
        didSet {
        print("已经将日期从 \(oldValue) 设定至 \(date)")
        }
} init() { date = NSDate() }
}
let foo = MyClass() foo.date = foo.date.dateByAddingTimeInterval(10086)
// 输出 // 即将将日期从 2015-07-16 16:01:49 +0000 设定至 2015-07-16 18:49:55 +0000
// 已经将日期从 2015-07-16 16:01:49 +0000 设定至 2015-07-16 18:49:55 +0000