var score = 0 // Variable
let pi = 3.14 // Constant
var greeting = "Hello"
var numberOfToys = 8
var isMorning = true
var numberOfToys: Int = 8
numberOfToys += 1
print(numberOfToys)
// prints "9"
var greeting: String = "Hello"
var numberOfToys: Int = 8
var isMorning: Bool = true
var price: Double = 8.99
+ Add- Subtraction* Multiplication/ Division% Remaindervar x = 0
x = 4 + 2 // x is now 6
x = 4 - 2 // x is now 2
x = 4 * 2 // x is now 8
x = 4 / 2 // x is now 2
x = 4 % 2 // x is now 0
+= Adds and assigns sums-= subtract and assign the difference*= Multiplication and assignment/= Divide and assign quotient%= Divide and assign remaindervar numberOfDogs = 100
numberOfDogs += 1
print("There are \(numberOfDogs) Dalmatians!")
// print: There are 101 Dalmatians!
var x = 0
x = 4 + 2 // x is now 6
x = 4 - 2 // x is now 2
x = 4 * 2 // x is now 8
x = 4 / 2 // x is now 2
x = 4 % 2 // x is now 0
+= 加并赋值-= 减并赋值*= 乘并赋值/= 除并赋值商%= 取余并赋值复合赋值运算符
var numberOfDogs = 100
numberOfDogs += 1
print("There are \(numberOfDogs) Dalmatians!")
// print: There are 101 Dalmatians!
var apples = 6
print("I have \(apples) apples!")
// print: I have 6 apples!
let myLongString = """
Swift?
This is my favorite language!
Yeah!
"""
// This line represents a comment in Swift.
/*
This is all commented out.
None will run!
*/
let player = ("Maya", 5, 150)
print(player) // ("Maya", 5, 150)
print("\(player.0): level \(player.1), \(player.2) pts") // Maya: level 5, 150 pts
let player = (name: "Maya", level: 5)
let (currentName, curLevel) = player
print("\(currentName): level \(curLevel)")
// print: Maya: level 5
// MARK: -view settings
MARK 可用于在导航栏显示注释分区
// TODO: update logic to accommodate data changes
TODO 用于显示待办事项提醒
// FIXME: Fix buggy behavior when making changes to existing entries
FIXME 用于显示需要修复事项的提醒
使用 var 声明变量:
var greeting = "Hello"
var numberOfToys = 8
var isMorning = true
为清晰起见,变量声明可包含类型标注:
var greeting: String = "Hello"
var numberOfToys: Int = 8
var isMorning: Bool = true
变量可变,其值可以改变:
var numberOfToys: Int = 8
numberOfToys += 1
print(numberOfToys)
// print "9"
使用 let 声明常量:
let greeting = "Hello"
let numberOfToys = 8
let isMorning = true
为清晰起见,常量声明可包含类型标注:
let greeting: String = "Hello"
let numberOfToys: Int = 8
let isMorning: Bool = true
常量不可变,其值不能改变:
let numberOfToys: Int = 8
numberOfToys += 1
// Error: numberOfToys is immutable
import Foundation
let df = DateFormatter()
df.dateFormat = "d MMMM yyyy"
guard var birth = df.date(from: "5 June 1999") else {
print("Date is not valid")
return
}
var age: Int {
Calendar.current
.dateComponents([.year],
from: birth,
to: Date()).year!
}
print(age) // 23
guard let birth2 = df.date(from: "5 June 2002") else {
print("Date is not valid")
return
}
birth = birth2
print(age) // 20
下例中,distanceInFeet 有 getter 与 setter。由于存在 setter,getter 需要
关键字 get:
var distanceInMeters: Float = 100
var distanceInFeet: Float {
get {
distanceInMeters *3.28
}
set(newDistance) {
distanceInMeters = newDistance /3.28
}
}
print(distanceInMeters) // 100.0
print(distanceInFeet) // 328.0
distanceInFeet = 250
print(distanceInMeters) // 76.21951
print(distanceInFeet) // 250.0
distanceInMeters = 800
print(distanceInMeters) // 800.0
print(distanceInFeet) // 2624.0
var distance = 5 {
willSet {
print("The distance will be set")
}
}
distance = 10 // print: distance will be set
可在 willSet 中访问新值:
var distance = 5 {
willSet(newDistance) {
print("The distance will be set \(newDistance)")
}
}
distance = 10 // print: distance will be set to 10
willSet 可在设置变量值之前执行代码
var distance = 5 {
didSet {
print("The distance is set to \(distance)")
print("Its old value is: \(oldValue)")
}
}
distance = 10 // print: distance will be set to 10
// print: its old value is: 5
var distance = 5 {
willSet(newDistance) {
print("The distance will be set to \(newDistance)")
}
didSet {
print("The distance is set to \(distance)")
print("Its old value is: \(oldValue)")
}
}
distance = 10
var halloween = true
if halloween {
print("Trick or treat!")
}
// print: Trick or treat!
if 5 > 3 {
print("5 is greater than 3")
} else {
print("5 is not more than 3")
}
// output: "5 is greater than 3"
var turbulence = false
if turbulence {
print("Please sit down.")
} else {
print("You are free to move around.")
}
// print: You are free to move around.
var weather = "rainy"
if weather == "sunny" {
print("Get some sunscreen")
} else if weather == "rainy" {
print("Take an umbrella")
} else if weather == "snowing" {
print("Put on your snow boots")
} else {
print("Invalid weather")
}
// print: take an umbrella
5 > 1 // true
6 < 10 // true
2 >= 3 // false
3 <= 5 // true
"A" == "a" // false
"B" != "b" // true
-< 小于
-> 大于
-<= 小于等于
->= 大于等于
-== 等于
等于
-!= 不等于
a...b // numbers between a and b (including both a and b)
a..<b // numbers between a and b (including a but excluding b)
...b // numbers till b (including b)
-a...b 闭区间
-a..<b 半开区间
-...b 单侧区间
var driverLicense = true
driverLicense
? print("driver seat") : print("passenger seat")
// print: driver's seat
var secondaryColor = "green"
switch secondaryColor {
case "orange":
print("A mixture of red and yellow")
case "purple":
print("A mix of red and blue")
default:
print("This may not be a secondary color")
}
// print: mix of blue and yellow
let year = 1905
var artPeriod: String
switch year {
case 1860...1885:
artPeriod = "Impressionism"
case 1886...1910:
artPeriod = "Post-Impressionism"
default:
artPeriod = "Unknown"
}
// print: post-impressionism
let service = "Seamless"
switch service {
case "Uber", "Lyft":
print("travel")
case "DoorDash", "Seamless", "GrubHub":
print("Restaurant delivery")
case "Instacart", "FreshDirect":
print("Grocery Delivery")
default:
print("Unknown service")
}
// print: restaurant takeaway
let num = 7
switch num {
case let x where x % 2 == 0:
print("\(num) is even")
case let x where x % 2 == 1:
print("\(num) odd number")
default:
print("\(num) is invalid")
}
// print: 7 odd
!true // false
!false //true
true && true // true
true && false // false
false && true // false
false && false // false
true || true // true
true || false // true
false || true // true
false || false // false
!false && true || false // true
!false && true 先求值并返回 true,接着表达式 true || false 求值并返回
最终结果为 true
false || true && false // false
true && false 先求值返回 false,接着表达式 false || false 求值并返回
最终结果为 false
// without parentheses:
true || true && false || false
//----> true
// with brackets:
(true || true) && (false || false)
//----> false
func greet(name: String?) {
guard let unwrapped = name else {
print("Hello guest!")
return
}
print("Hello \(unwrapped)!")
}
greet(name: "Asma") // output: Hello Asma!
greet(name: nil) // output: Hello guest!
let zeroToThree = 0...3
//zeroToThree: 0, 1, 2, 3
for oddNum in stride(from: 1, to: 5, by: 2) {
print(oddNum)
}
// print: 1
// print: 3
for char in "hehe" {
print(char)
}
// print: h
// print: e
// print: h
// print: e
for num in 0...5 {
if num % 2 == 0 {
continue
}
print(num)
}
// print: 1
// print: 3
// print: 5
continue 关键字会强制循环进入下一次迭代
for char in "supercalifragilistic" {
if char == "c" {
break
}
print(char)
}
// print: s
// print: u
// print: p
// print: e
// print: r
for _ in 1...3 {
print("Ole")
}
// print: Ole
// print: Ole
// print: Ole
var counter = 1
var stopNum = Int.random(in: 1...10)
while counter < stopNum {
print(counter)
counter += 1
}
// loop to print until the stop condition is met
while 循环接受一个条件,并在条件为 true 时持续执行循环体。若
条件永不变为 false,循环会一直运行,程序将陷入 infinite loop(无限循环)
var scores = [Int]()
// array is empty: []
var grocery = ["🥓", "🥞", "🍪", "🥛", "🍊"]
print(grocery.count)
// print: 5
索引表示有序列表中元素的位置,使用
下标语法 array[index] 取出单个元素。
var vowels = ["a", "e", "i", "o", "u"]
print(vowels[0]) // prints: a
print(vowels[1]) // prints: e
print(vowels[2]) // print: i
print(vowels[3]) // prints: o
print(vowels[4]) // prints: u
注意:Swift 数组从零开始索引,即第一个元素的索引为 0。
// use type inference:
var snowfall = [2.4, 3.6, 3.4, 1.8, 0.0]
// explicit type:
var temp: [Int] = [33, 31, 30, 38, 44]
var teams = [Int](repeating: 0, count: 3)
print(teams) // prints: [0, 0, 0]
// or with Array type
var sizes = Array<Int>(repeating: 0, count: 3)
print(sizes) // prints: [0, 0, 0]
var gymBadges = ["Boulder", "Cascade"]
gymBadges.append("Thunder")
gymBadges += ["Rainbow", "Soul"]
// ["Boulder", "Cascade", "Thunder",
// "Rainbow", "Soul"]
var moon = ["🌖", "🌗", "🌘", "🌑"]
moon.insert("🌕", at: 0)
// ["🌕", "🌖", "🌗", "🌘", "🌑"]
moon.remove(at: 4)
// ["🌕", "🌖", "🌗", "🌘"]
var employees = ["Peter", "Denial", "Jame"]
for person in employees {
print(person)
}
// print: Peter
// print: Denial
// print: Jam
var paintingsInMOMA: Set = [
"The Dream",
"The Starry Night",
"The False Mirror"
]
可用集合(Set)存储相同数据类型的 unique(唯一)元素
var team = Set<String>()
print(team)
// print: []
var vowels: Set = ["a", "e", "i", "o","u"]
要创建带初始值的集合,在赋值运算符前使用 Set 关键字。
var cookieJar: Set = [
"Chocolate Chip",
"Oatmeal Raisin"
]
// add a new element
cookieJar.insert("Peanut Butter Chip")
var oddNumbers: Set = [1, 2, 3, 5]
// remove existing element
oddNumbers.remove(2)
// remove all elements
oddNumbers.removeAll()
var names: Set = ["Rosa", "Doug", "Waldo"]
print(names.contains("Lola")) // print: false
if names.contains("Waldo"){
print("There's Waldo!")
} else {
print("Where's Waldo?")
}
// print: There's Waldo!
var emptyList = [String]()
print(emptyList.isEmpty) // print: true
var populatedList: [Int] = [1, 2, 3]
print(populatedList.isEmpty) // print: false
var recipe: Set = ["Egg", "Flour", "Sugar"]
for ingredient in recipe {
print ("Include \(ingredient) in the recipe")
}
var emptySet = Set<String>()
print(emptySet.isEmpty) // print: true
var populatedSet: Set = [1, 2, 3]
print(populatedSet.isEmpty) // print: false
var band: Set = ["Peter", "Denial", "Jame"]
print("The band has \(band.count) players.")
// print: Band has 4 players.
var setA: Set = ["A", "B", "C", "D"]
var setB: Set = ["C", "D", "E", "F"]
var setC = setA.intersection(setB)
print(setC) // print: ["D", "C"]
var setA: Set = ["A", "B", "C", "D"]
var setB: Set = ["C", "D", "E", "F"]
var setC = setA.union(setB)
print(setC)
// print: ["B", "A", "D", "F", "C", "E"]
var setA: Set = ["A", "B", "C", "D"]
var setB: Set = ["C", "D", "E", "F"]
var setC = setA.symmetricDifference(setB)
print(setC)
// print: ["B", "E", "F", "A"]
var setA: Set = ["A", "B", "C", "D"]
var setB: Set = ["C", "D"]
var setC = setA.subtracting(setB)
print(setC)
// print: ["B", "A"]
var dictionaryName = [
"Key1": "Value1",
"Key2": "Value2",
"Key3": "Value3"
]
由数据对或键值对组成的 unordered(无序)集合
var fruitStand = [
"Coconuts": 12,
"Pineapples": 12,
"Papaya": 12
]
每个 key 都是 unique(唯一)的,即使它们包含相同的 value
var numberOfSides = [
"triangle": 3,
"square": 4,
"rectangle": 4
]
仅包含 String 键与 Int 值
var employeeID = [
"Hamlet": 1367,
"Horatio": 8261,
"Ophelia": 9318
]
// initializer syntax:
var yearlyFishPopulation = [Int: Int]()
// Empty dictionary literal syntax:
var yearlyBirdPopulation: [Int: Int] = [:]
var pronunciation = [
"library": "lai·breh·ree",
"apple": "a·pl"
]
// new key: "programming", new value: "prow gra"
pronunciation["programming"] = "prow·gra"
var bookShelf = [
"Goodnight": "Margaret Wise Brown",
"The BFG": "Roald Dahl",
"Falling Up": "Shel Silverstein",
"No, David!": "David Shannon"
]
// remove value by setting key to nil
bookShelf["The BFG"] = nil
// remove value using .removeValue()
bookShelf.removeValue(forKey: "Goodnight")
// remove all values
bookShelf.removeAll()
var change = [
"Quarter": 0.29,
"Dime": 0.15,
"Nickel": 0.05
]
// Change the value using subscript syntax
change["Quarter"] = .25
// Change the value using .updateValue()
change.updateValue(.10, forKey: "Dime")
要修改键值对的值,可使用 .updateValue() 方法,或通过在字典名后追加方括号
[ ] 并写入已有键,再接赋值运算符 (= ) 与
修改后的值
var bakery = [String:Int]()
// check if the dictionary is empty
print(bakery.isEmpty) // prints true
bakery["Cupcakes"] = 12
// check if the dictionary is empty
print(bakery.isEmpty) // print false
var fruitStand = [
"Apples": 12,
"Oranges", 17
]
print(fruitStand.count) // print: 2
var hex = [
"red": "#ff0000",
"yellow": "#ffff00",
"blue": "#0000ff",
]
print("Blue hexadecimal code \(hex["blue"])")
// print: blue hex code 可选("#0000ff")
if let redHex = hex["red"] {
print("red hexadecimal code \(redHex)")
}
// print: red hex code #ff0000
将键值对的值赋给变量会返回 可选 值。要提取值,请使用 可选 展开
var emojiMeaning = [
"🤔": "Thinking Face",
"😪": "Sleepy Face",
"😵": "Dizzy Face"
]
// loop through keys and values
for (emoji, meaning) in emojiMeaning {
print("\(emoji) is called '\(meaning)Emoji'")
}
// iterate through keys only
for emoji in emojiMeaning.keys {
print(emoji)
}
// iterate through values only
for meaning in emojiMeaning.values {
print(meaning)
}
func washCar() -> Void {
print("Soap")
print("Scrub")
print("Rinse")
print("Dry")
}
func greetLearner() {
print("Welcome to qr.warpnav.com!")
}
// function call:
greetLearner()
// print: Welcome to qr.warpnav.com!
let birthYear = 1994
var currentYear = 2020
func findAge() -> Int {
return currentYear-birthYear
}
print(findAge()) // prints: 26
func convertFracToDec(numerator: Double, denominator: Double) -> Double {
return numerator / denominator
}
let decimal = convertFracToDec(numerator: 1.0, denominator: 2.0)
print(decimal) // prints: 0.5
func findDiff(_ a: Int, b: Int) -> Int {
return a -b
}
print(findDiff(6, b: 4)) // prints: 2
func smartphoneModel() -> (name: String, version: String, yearReleased: Int) {
return ("iPhone", "8 Plus", 2017)
}
let phone = smartphoneModel()
print(phone.name) // print: iPhone
print(phone.version) // print: 8 Plus
print(phone.yearReleased) // print: 2017
func findSquarePerimet(side: Int) -> Int {
return side *4
}
let perimeter = findSquarePerimet(side: 5)
print(perimeter) // print: 20
// Parameter: side
// Argument: 5
func nextTotalSolarEclipse() -> String {
"April 8th, 2024 🌎"
}
print(nextTotalSolarEclipse())
// print: April 8th, 2024 🌎
func greet(person: String = "guest") {
print("Hello \(person)")
}
greet() // Hello guest
greet(person: "Aliya") // Hello Aliya
var currentSeason = "Winter"
func season(month: Int, name: inout String) {
switch month {
case 1...2:
name = "Winter ⛄️"
case 3...6:
name = "Spring 🌱"
case 7...9:
name = "Summer ⛱"
case 10...11:
name = "Autumn 🍂"
default:
name = "Unknown"
}
}
season(month: 4, name: ¤tSeason)
print(currentSeason) // Spring 🌱
func totalStudent(data: String...) -> Int {
let numStudents = data.count
return numStudents
}
print(totalStudent(data: "Denial", "Peter"))
// print: 2
func getFirstInitial(from name: String?) -> String? {
return name?.first
}
函数可接受并返回 可选 类型。当函数无法返回所请求类型的合理实例
时,应返回 nil
struct Building {
var address: String
var floors: Int
init(address: String, floors: Int) {
self.address = address
self.floors = floors
}
}
结构体用于在代码中程序化表示现实对象。使用
struct 关键字,后跟名称,再跟包含属性与方法的主体
struct Car {
var numOfWheels = 4
var topSpeed = 80
}
var reliantRobin = Car(numOfWheels: 3)
print(reliantRobin.numOfWheels) // prints: 3
print(reliantRobin.topSpeed) // print: 80
struct Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
// Person instance:
var morty = Person(name: "Peter", age: 14)
struct TV {
var size: Int
var type: String
init(size: Int, type: String) {
self.size = size
self.type = type
}
}
使用 TV 类
var newTV = TV(size: 65, type: "LED")
print(type(of: "abc")) // print: String
print(type(of: 123)) // print: 123
struct Menu {
var menuItems = ["Fries", "Burgers"]
mutating func addToMenu(dish: String) {
self.menuItems.append(dish)
}
}
使用 Menu 类
var dinerMenu = Menu()
dinerMenu.addToMenu(dish: "Toast")
print(dinerMenu.menuItems)
// prints: ["Fries", "Burgers", "Toast"]
struct Dog {
func bark() {
print("Woof")
}
}
let fido = Dog()
fido.bark() // prints: Woof
class Player {
var name: String
init(name: String) {
self.name = name
}
}
var player1 = Player(name: "Tomoko")
var player2 = player1
player2.name = "Isabella"
print(player1.name) // Isabella
print(player2.name) // Isabella
class Person {
var name = ""
var age = 0
}
var sonny = Person()
// sonny is now an instance of Person
class Fruit {
var hasSeeds = true
var color: String
init(color: String) {
self.color = color
}
}
使用 Fruit 类
let apple = Fruit(color: "red")
类可通过 init() 方法及相应初始化属性进行初始化。在 init()
方法中,使用 self 关键字引用正在赋属性值的类实例
var ferris = Student()
ferris.name = "Ferris Bueller"
ferris.year = 12
ferris.gpa = 3.81
ferris.honors = false
假设有一个 BankAccount 类:
class BankAccount {
var balance = 0.0
func deposit(amount: Double) {
balance += amount
}
func withdraw(amount: Double) {
balance -= amount
}
}
SavingsAccount 继承 BankAccount 类
class SavingsAccount: BankAccount {
var interest = 0.0
func addInterest() {
let interest = balance *0.005
self.deposit(amount: interest)
}
}
新的 SavingsAccount 类(子类)自动获得 BankAccount 类
(超类)的全部特性。此外,SavingsAccount 还定义了 .interest 属性与 .addInterest() 方法。
使用数据类型
class Student {
var name: String
var year: Int
var gpa: Double
var honors: Bool
}
使用默认属性值
class Student {
var name = ""
var gpa = 0.0
var honors = false
}
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
Resolution 结构体定义与 VideoMode 类定义仅描述 Resolution
或 VideoMode,创建结构体或类的实例:
let resolution = Resolution(width: 1920)
let someVideoMode = VideoMode()
enum Day {
case monday
case tuesday
case wednesday
case thursday
case friday
case saturday
case sunday
}
let casualWorkday: Day = .friday
enum Dessert {
case cake(flavor: String)
case vanillaIceCream(scoops: Int)
case brownie
}
let customerOrder: Dessert = .cake(flavor: "Red Velvet")
switch customerOrder {
case let .cake(flavor):
print("You ordered a \(flavor) cake")
case .brownie:
print("You ordered a chocolate cake")
}
// prints: "You ordered a red velvet cake"
enum Season: CaseIterable {
case winter
case spring
case summer
case falls
}
for season in Season.allCases {
print(season)
}
遵循 CaseIterable 协议即可访问 allCases 属性,它返回枚举全部 case 的数组
该枚举
enum Beatle: String {
case john paul george ringo
}
print("The Beatles are \(Beatle.john.rawValue).")
// print: The Beatles are john.
enum Dessert {
case cake(flavor: String)
case vanillaIceCream(scoops: Int)
case brownie
}
let order: Dessert = .cake(flavor: "Red Velvet")
enum Traffic {
case light
case heavy
mutating func reportAccident() {
self = .heavy
}
}
var currentTraffic: Traffic = .light
currentTraffic.reportAccident()
// currentTraffic is now .heavy
与类和结构体一样,枚举也可有实例方法。若实例方法会修改
枚举,则需标记为 mutating
enum Hello: String {
case english = "Hello"
case japanese = "Hello!"
case emoji = "👋"
}
let hello1 = Hello(rawValue: "Hello!")
let hello2 = Hello(rawValue: "Привет")
print(hello1) // 可选(Hello.japanese)
print(hello2) // nil
enum ShirtSize: String {
case small = "S"
case medium = "M"
case large = "L"
case extraLarge = "XL"
var description: String {
return "The size of this shirt is \(self.rawValue)"
}
}
扩展用于为已有的类、结构体、枚举或协议类型添加新功能。 包括添加新方法、属性、初始化器等。
扩展特别适合在不修改原始类型的情况下组织与模块化代码, 尤其是在无法访问原始源代码时。
extension SomeType {
// New functionalities to be added
}
extension Int {
var isEven: Bool {
self % 2 == 0
}
}
print(4.isEven) // Outputs: true
print(7.isEven) // Outputs: false
extension String {
func reverse() -> String {
String(self.reversed())
}
}
print("abc".reverse()) // Output: cba
extension Int {
mutating func square() {
self = self * self
}
}
var number = 5
number.square()
print(number) // Output: 25
extension Date {
init?(timestamp: Double) {
self.init(timeIntervalSince1970: timestamp)
}
}
let timestamp = 1693982400.0 // Unix timestamp for 2023-09-06 06:40:00
if let date = Date(timestamp: timestamp) {
print(date) // Output: 2023-09-06 06:40:00 +0000
}
extension String {
subscript(index: Int) -> Character {
self[self.index(startIndex, offsetBy: index)]
}
}
print("Swift"[0]) // Output: S
print("Swift"[1]) // Output: w
print("Swift"[2]) // Output: i
print("Swift"[3]) // Output: f
print("Swift"[4]) // Output: t
就“希望某功能在所有类中都可用”而言,它很像抽象类: 实现某协议的所有类中可用(无需继承公共基类)。
// Define a protocol
protocol Describable {
func describe() -> String
}
// Provide a default implementation using a protocol extension
extension Describable {
func describe() -> String {
"This is a generic description"
}
}
// Define a struct that conforms Describable protocol
struct Person: Describable {
var name: String
var age: Int
// Overriding the default implementation
func describe() -> String {
"My name is \(name) and I am \(age) years old."
}
}
struct Employee: Describable {
var name: String
var age: Int
// Using the default implementation
}
// By just implementing the protocol the describe() method is available
let person = Person(name: "Ivan", age: 21)
let employee = Employee(name: "Saul", age: 25)
print(person.describe()) // Output: My name is Ivan and I am 21 years old.
print(employee.describe()) // Output: This is a generic description
当我们想为遵循特定协议或满足 某些条件时特别有用。
extension Array where Element: Numeric {
func sum() -> Element {
reduce(0, +)
}
}
let numbers = [1, 2, 3, 4, 5]
print(numbers.sum()) // Output: 15
let doubles = [1.5, 2.5, 3.5]
print(doubles.sum()) // Output: 7.5
// This will not work because String is not Numeric
// let strings = ["a", "b", "c"]
// print(strings.sum()) // Error: Cannot invoke 'sum' with an array of strings
扩展不限于添加功能,也便于组织代码。我们可以把相关的 方法、属性或视图到不同的扩展中。
import SwiftUI
struct HomeView: View {
var body: some View {
ScrollView {
header
// Add other views
}
}
}
extension HomeView {
private var header: some View {
Text("Header ...")
}
}
#Preview {
HomeView()
}
Swift 泛型允许我们创建可与任意数据类型协作的函数、类、结构体和协议。 与任意数据类型一起使用。
泛型让我们写出清晰简洁、适用于任意数据类型的代码。通过使用占位符(如 T),这
降低引入缺陷的风险。
func foo<T, U>(a: T, b: U) {
// ...
}
struct Foo<T, U> {
var a: T
// ...
}
占位符 T 是类型参数示例,写在尖括号中(如 <T>)。
struct Box<T> {
var value: T
}
let intBox = Box(value: 10)
let stringBox = Box(value: "Hello")
print(intBox.value) // Output: 10
print(stringBox.value) // Output: "Hello"
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var a = 10
var b = 20
swapValues(&a, &b)
print(a) // Output: 20
print(b) // Output: 10
var c = "Hello"
var d = "World"
swapValues(&c, &d)
print(c) // Output: "World"
print(d) // Output: "Hello"
func sum<T: Numeric>(_ array: [T]) -> T {
array.reduce(0, +)
}
print(sum([1, 1.5, 2])) // Output: 4.5
// This will not work because String is not Numeric
// print(sum(["a", "b", "c"]))
// Error: function 'sum' requires that 'String' conform to 'Numeric'
protocol Foo {
associatedtype T
func foo() -> T
}
关联类型用于在协议中定义稍后指定的类型占位符,充当 泛型占位符。具体类型不在协议中定义,而是在类、结构体 或枚举遵循该协议时再确定。
protocol Storage {
associatedtype Item
func store(item: Item)
func retrieve() -> Item?
}
class SimpleStorage<T>: Storage {
private var items: [T] = []
func store(item: T) {
items.append(item)
}
func retrieve() -> T? {
return items.isEmpty ? nil : items.removeLast()
}
}
let intStorage = SimpleStorage<Int>()
intStorage.store(item: 42)
print(intStorage.retrieve() ?? "Empty") // Output: 42
泛型类型别名可为已有类型创建新名称(即不会引入新类型)。
typealias StringDictionary<T> = [String: T]
typealias IntFunction<T> = (Int) -> Int
typealias Vector<T> = (T, T, T)