funcarithmeticMean(_numbers: Double...) -> Double { var total: Double=0 for number in numbers { total += number } return total /Double(numbers.count) } arithmeticMean(1, 2, 3, 4, 5) // 返回 3.0, 是这 5 个数的平均数。 arithmeticMean(3, 8.25, 18.75) // 返回 10.0, 是这 3 个数的平均数。
输入输出参数
参数类型前加inout标记,调用时在变量前加&
1 2 3 4 5 6 7 8 9 10
funcswapTwoInts(_a: inoutInt, _b: inoutInt) { let temporaryA = a a = b b = temporaryA } var someInt =3 var anotherInt =107 swapTwoInts(&someInt, &anotherInt) print("someInt is now \(someInt), and anotherInt is now \(anotherInt)") // 打印“someInt is now 107, and anotherInt is now 3”
函数类型
作为参数类型
1 2 3 4 5 6 7 8 9
//函数类型 (Int, Int) -> Int funcaddTwoInts(_a: Int, _b: Int) -> Int { return a + b } funcprintMathResult(_mathFunction: (Int, Int) -> Int, _a: Int, _b: Int) { print("Result: \(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // 打印“Result: 8”
let strings = numbers.map { (number) -> Stringin//number类型无需指定,会自动推断 var number = number //闭包或函数的参数总是常量,故需赋值给一个局部变量 var output ="" repeat { output = digitNames[number %10]!+ output number /=10 } while number >0 return output } // strings = ["OneSix", "FiveEight", "FiveOneZero"]
enumArithmeticExpression { case number(Int) indirectcase addition(ArithmeticExpression, ArithmeticExpression) indirectcase multiplication(ArithmeticExpression, ArithmeticExpression) } indirectenumArithmeticExpression { case number(Int) case addition(ArithmeticExpression, ArithmeticExpression) case multiplication(ArithmeticExpression, ArithmeticExpression) }
let five =ArithmeticExpression.number(5) let four =ArithmeticExpression.number(4) let sum =ArithmeticExpression.addition(five, four) let product =ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
structFixedLengthRange { var firstValue: Int let length: Int } let rangeOfFourItems =FixedLengthRange(firstValue: 0, length: 4) // 该区间表示整数 0,1,2,3 rangeOfFourItems.firstValue =6 // 尽管 firstValue 是个可变属性,但这里还是会报错
// 定义 @propertyWrapper structTwelveOrLess { privatevar number =0 var wrappedValue: Int { get { return number } set { number =min(newValue, 12) } } } // 使用 structSmallRectangle { @TwelveOrLessvar height: Int @TwelveOrLessvar width: Int }
var rectangle =SmallRectangle() print(rectangle.height) // 0
@propertyWrapper structSmallNumber { privatevar number: Int private(set)var projectedValue: Bool
var wrappedValue: Int { get { return number } set { if newValue >12 { number =12 projectedValue =true } else { number = newValue projectedValue =false } } }
init() { self.number =0 self.projectedValue =false } } structSomeStructure { @SmallNumbervar someNumber: Int } var someStructure =SomeStructure()
structPoint { var x =0.0, y =0.0 funcisToTheRightOf(x: Double) -> Bool { returnself.x > x } }
在实例方法中修改值类型
结构体和枚举是值类型,默认情况下,值类型的属性不能在它的实例方法中被修改
想修改,需在方法前加mutating关键字
不能在结构体类型的常量上调用可变方法
1 2 3 4 5 6 7 8 9 10 11 12 13
structPoint { var x =0.0, y =0.0 mutatingfuncmoveBy(xdeltaX: Double, ydeltaY: Double) { x += deltaX y += deltaY } } var somePoint =Point(x: 1.0, y: 1.0) somePoint.moveBy(x: 2.0, y: 3.0) // 打印“The point is now at (3.0, 4.0)” let fixedPoint =Point(x: 3.0, y: 3.0) fixedPoint.moveBy(x: 2.0, y: 3.0) // 这里将会报告一个错误
subscript(index: Int) -> Int { get { // 返回一个适当的 Int 类型的值 } set(newValue) { // 执行适当的赋值操作 } }
structTimesTable { let multiplier: Int subscript(index: Int) -> Int { return multiplier * index } } let threeTimesTable =TimesTable(multiplier: 3) print("six times three is \(threeTimesTable[6])") // 打印“six times three is 18”
下标选项
支持多个参数(但不能用inout参数)
1 2 3 4 5 6 7 8 9 10
subscript(row: Int, column: Int) -> Double { get { assert(indexIsValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } }
继承
Swift 中的类并不是从一个通用的基类继承而来的。如果你不为自己定义的类指定一个超类的话,这个类就会自动成为基类。
funcsomeThrowingFunction() throws -> Int { // ... }
let x =try? someThrowingFunction()
let y: Int? do { y =try someThrowingFunction() } catch { y =nil }
defer用于函数退出或作用域结束时清理工作
函数正常结束或提前结束都会执行defer内容
1 2 3 4 5 6 7 8 9 10 11 12
funcprocessFile(filename: String) throws { if exists(filename) { let file =open(filename) defer { close(file) } whilelet line =try file.readline() { // 处理文件。 } // close(file) 会在这里被调用,即作用域的最后。 } }
并发
async标记异步函数
调用异步函数前加await代表这个方法被挂起
1 2 3 4 5 6 7 8 9 10
funclistPhotos(inGalleryname: String) async -> [String] { let result =// 省略一些异步网络请求代码 return result }
let photoNames =await listPhotos(inGallery: "Summer Vacation") let sortedNames = photoNames.sorted() let name = sortedNames[0] let photo =await downloadPhoto(named: name) show(photo)
类型转换
检查类型 is
1 2 3 4 5 6 7 8 9 10
var movieCount =0 var songCount =0 for item in library { if item isMovie { movieCount +=1 } elseif item isSong { songCount +=1 } } print("Media library contains \(movieCount) movies and \(songCount) songs")
向下转型 as?或as!
1 2 3 4 5 6 7
for item in library { iflet movie = item as?Movie { print("Movie: \(movie.name), dir. \(movie.director)") } elseiflet song = item as?Song { print("Song: \(song.name), by \(song.artist)") } }
Any 和 AnyObject 的类型转换
Any 可以表示任何类型,包括函数类型。
AnyObject 可以表示任何类类型的实例
扩展
添加计算型实例属性和计算型类属性
1 2 3 4 5 6 7 8 9
extensionDouble { var km: Double { returnself*1_000.0 } var m: Double { returnself } var cm: Double { returnself/100.0 } var mm: Double { returnself/1_000.0 } var ft: Double { returnself/3.28084 } } let oneInch =25.4.mm print("One inch is \(oneInch) meters")
classDice { let sides: Int let generator: RandomNumberGenerator init(sides: Int, generator: RandomNumberGenerator) { self.sides = sides self.generator = generator } funcroll() -> Int { returnInt(generator.random() *Double(sides)) +1 } } //任何遵循了 RandomNumberGenerator 协议的类型的实例都可以赋值给 generator
var d6 =Dice(sides: 6, generator: LinearCongruentialGenerator()) for_in1...5 { print("Random dice roll is \(d6.roll())") } // Random dice roll is 3 // Random dice roll is 5 // Random dice roll is 4 // Random dice roll is 5 // Random dice roll is 4
classMyClass { var delegate: MyDelegate? funcdoSomething() { print("let's do something") delegate?.myplay() } }
classSomeClass: MyDelegate { funcmyplay() { print("SomeClass is playing") } } let a =SomeClass() let b =MyClass() b.delegate = a b.doSomething() //let's do something //SomeClass is playing
//T类型必须能被比较(Equatable要求实现==和!=) funcfindIndex<T: Equatable>(ofvalueToFind: T, inarray:[T]) -> Int? { for (index, value) in array.enumerated() { if value == valueToFind { return index } } returnnil }