let 声明常量,var 声明变量
var myVariable = 2
myVariable = 3
let myConstant = 4
let explicitDouble: Double = 70 // 显式声明类型
变量的值不会做隐式的类型转换,如果需要转换类型,需要显式实例化,如:
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
print(widthLabel)
有一个简答的方法在字符串中引用变量,使用 \()
,如:
let apples = 3
let oranges = 4
let fruitsSummary = "I have \(apples + oranges) pieces of fruit."
使用 []
来创建数组或者字典,同样地使用 target[index]
来获取元素:
var list = ["apple", "orange", "banana"]
var list[1] = "pear"
var jobs = [
"Peter": "Developer",
"Mike": "Worker"
]
jobs["Mike"] = "Writer"
创建空的数组或者字典,可以使用初始化语法:
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
// 如果类型可以推断,那么可以不显式声明类型
shoppingList = []
occupations = [:]
使用 if
和 switch
来进行条件判断,使用 for-in
,for
,while
,repeat-while
来进行循环控制。
条件或者循环变量的括号可以写也可以不写,执行的代码的 {}
则是必须的。
let scores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in scores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
print(teamScore)
if
语句中,条件判断必须是 Boolean 类型,如上, if score { ... }
则会报错。
可以使用 let
和 if
搭配来判断可能是 nil 的值,在类型声明后加 ?
来表示这个值是可选的,可能是 nil。
在 swift 中的 ?
很特别,如果在 ?
之前的值是 nil,那么在 ?
之后的会被忽略,并且整个表达式的值为 nil。
var optionalString: String? = "Hello"
print(optionalString == nil)
var optionalName: String? = "Boom Lee"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
let 可以用于传递匹配对应的值,例如:
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("1")
case "cucumber", "watercress":
print("2")
case let x where x.hasSuffix("pepper"):
print("3")
default:
print("default")
}
留意 case "cucumber", "watercress":
可以这么使用来处理或逻辑。
留意 case let x where x.hasSuffix("pepper"):
使用 let 来获取对应的值,并且使用 where 来进行判断。
这里不需要 break
,默认的逻辑是不会接着 case
执行下次。
使用 fon-in
来循环遍历字典。字典是一种无序集合的数据类型,for-�in
提供了对应的 key-value。
let numbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in numbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
print(largest)
使用 while
来循环代码直到某一个状态值符合条件。使用 repeat
,把 while
放在代码块之后,确保代码块至少至少执行一次。
var n = 2
while n < 100 {
n = n * 2
}
print(n)
var m = 2
repeat {
m = m * 2
} while m < 100
print(m)
可以使用 ..<
在循环中维持一个索引值,例如:
var first = 0
for i in 0..<4 {
first += i
}
print(first)
// 等价于
var second = 0
for var i = 0; i < 4; i++ {
second += i
}
print(second)
使用 func
来声明函数。使用 ->
来声明函数的返回类型。
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)"
}
greet("Boom", day: "Tuesday")
swift 的函数可以使用 ()
来返回多个值,并且这些值可以使用 name 或者序号来获取。
func calculate(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}
return (min, max, sum)
}
let statistics = calculate([5, 3, 100, 3, 9])
print(statistics.sum)
print(statistics.2)
swift 的函数可以接受不定量的参数,将其存放于一个数组中:
func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(32, 11, 23)
函数是可以嵌套的,并且内部的函数可以访问在外部函数声明的变量。
你可以使用嵌套的函数来组织很长或者很复杂的代码。函数在 swift 也是第一类型,这意味着你可以在函数中返回函数,或者使用函数作为参数。
func makeIncrementer() -> (Int -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var incrementer = makeIncrementer()
func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThenTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 11]
hasAnyMatches(numbers, condition: lessThenTen)
在 swift 中,函数实际上是一种闭包,即可延后调用的代码块。在闭包中的代码可以访问创建闭包时作用域中的变量和函数。
可以在 swift 中使用 {}
来创建一个闭包,使用 in
来区分参数,返回类型和代码块内容。
numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
使用闭包时有多种方式,如果是一个闭包的数据类型是已知的,例如函数的一个回调,那么你可以忽略参数类型,或者返回类型。单个语句的闭包会直接返回语句表达式的值。
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
你可以使用序号来引用参数,在很短的闭包中这种方式非常有用。
闭包是函数唯一的参数,可以直接忽略括号。
let sortedNumbers = numbers.sort { $0 > $1 }
print(sortedNumbers)
使用 class
加类名可以创建一个类。声明类属性如同声明变量和常量一样,但是它在类的上下文中。方法和函数的声明也是类似的。
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
创建一个类的实例,直接在类名后加 ()
即可,如:
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
构造函数的话,使用 init
来创建:
class NamedSpace {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
...
}
留意 self
可以用来区分 name
属性和 name
参数。传递给 init
的参数就和函数调用是一样的,实例化时传递即可。
使用 deinit
来创建一个析构函数,当一个对象回收时,如果你需要做一些清理工作的话,可以在 deinit
方法中处理。
类继承只需要在类声明后加要继承的父类,使用 :
即可。没有要求类必须继承于某一个根类,你可以视需要而定。
在子类中要覆写父类的方法时,需要在方法声明前加 override
,没有的话,编译时会报错。编辑器也会发现那些加了 override
但是却不是覆写父类的方法。
class Square: NamedSpace {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
除了简单的存储外,属性可以拥有 getter 和 setter 方法:
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
在 setter 中可以使用 newValue
名称来获取新设置的值,你也可以在 set 声明中使用 ()
来使用自定义的名称。
类的初始化方法中一般是有三个不同步骤:
- 设置子类声明的属性值
- 调用父类的初始化方法
- 修改子类定义的属性值,一些额外的初始化方法的调用等
如果你不需要计算属性的值,不希望使用 setter,但是需要在设置属性之前或者之后执行一些代码,这个时候可以使用 willSet
和 didSet
。
class TriangleAndSquare {
var triangle: EquilateralTriangle {
willSet {
square.sideLength = newValue.sideLength
}
}
var square: Square {
willSet {
triangle.sideLength = square.sideLength
}
}
...
}
使用 enum
来创建枚举类型,可以像类一样拥有方法:
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> Stirng {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.rawValue)
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.rawValue
如果枚举的原始值为 Int
,你只需要指定第一个原始值,如 case Ace = 1
,那么剩余的值会自动按序赋予。你也可以使用字符串或者浮点数作为枚举的原始值类型。
使用 rawValue
来获取枚举的一个成员的原始值。
你也可以通过的枚举的 init
方法传入一个原始值来进行枚举的实例化。如:
if let convertedRank = Rank(rawValue: 3) {
let three = convertedRank.simpleDescription()
}
枚举成员的值可以拥有一个确切的原始值,如果没有确切的原始值,也可以不用指定。
enum Suit {
case Spades, Hearts, Diamonds, Clubs
func simpleDescription() -> String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()
留意一下,这里的 Hearts
有两种引用方式,在 hearts
赋值时使用全称,Suit.Hearts
。而在 swict
中直接使用 .Hearts
,因为在上下文环境中已经可以确定 self
为 Suit。你可以在已知类型的情况下使用这种简短的写法。
使用 struct
来创建结构体,结构体支持很多类有的行为,如方法,构造器等。两者有一个最重要的区别是,在代码中进行传递时,如函数的参数,结构体通常是复制,而类是引用。
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
协议我们可以理解为类似接口的东西,在 swift 中,类,枚举,结构体都可以使用协议:
protocol Example {
var simpleDescription: String { get }
mutating func adjust()
}
class SimpleClass: Example {
var simpleDescription: String = "A simple class."
var anotherProperty: Int = 1
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
struct SimpleStructure: Example {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
注意 mutating
的使用,这个关键词用于表示方法将会修改这个结构体,而类通常默认方法可以修改自身,所以无需使用 mutating
来声明。
扩展可以用于在已有的类型上添加功能,例如新的方法或者可计算的属性。你可以使用扩展来把协议添加到已有的类型上。
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription)
使用 <>
来声明一个泛型的函数或者类型:
func repeatItem<Item>(item: Item, times: Int) -> [Item] {
var result = [Item]()
for _ in 0..<times {
result.append(item)
}
return result
}
repeatItem("knock", 3)
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)
swift 推荐的编码风格:https://github.com/raywenderlich/swift-style-guide