该备忘单提供了使用 Swift 的示例,涵盖 Swift 基础知识、控制流、类型、结构/类、运算符、函数方法等。
var score = 0 // 变量let pi = 3.14 // 常数var greeting = "Hello"var numberOfToys = 8var isMorning = truevar numberOfToys: Int = 8numberOfToys += 1print(numberOfToys) // 打印 "9"
var greeting: String = "Hello"var numberOfToys: Int = 8var isMorning: Bool = truevar price: Double = 8.99
+
添加-
减法*
乘法/
分配%
余数var x = 0x = 4 + 2 // x 现在是 6x = 4 - 2 // x 现在是 2x = 4 * 2 // x 现在是 8x = 4 / 2 // x 现在是 2x = 4 % 2 // x 现在是 0
var numberOfDogs = 100numberOfDogs += 1print("有 \(numberOfDogs) 个斑点狗!")// 打印: 有 101 个斑点狗!
+=
添加和分配总和-=
减去并分配差值*=
乘并赋值/=
除并分配商%=
除并分配余数var apples = 6print("I have \(apples) apples!")// 打印: I have 6 apples!
let myLongString = """Swift?这是我最喜欢的语言!"""
// 这一行表示 Swift 中的注释。/*这都被注释掉了。没有一个会跑!*/
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) = playerprint("\(currentName): level \(curLevel)")// 打印: Maya: level 5
// MARK: - 查看设置
MARK
可用于在栏中显示评论
// TODO: 更新逻辑以适应数据更改
TODO
用于显示需要完成的事情的提醒
// FIXME: 修复对现有条目进行更改时的故障行为
FIXME
用于显示需要修复的内容的提醒
变量用 var
声明:
var greeting = "你好"var numberOfToys = 8var isMorning = true
为了清楚起见,变量声明可以包含类型注释:
var greeting: String = "你好"var numberOfToys: Int = 8var isMorning: Bool = true
变量是可变的。 它们的值可以改变:
var numberOfToys: Int = 8numberOfToys += 1print(numberOfToys) // 打印“9”
常量用 let
声明:
let greeting = "Hello"let numberOfToys = 8let isMorning = true
为清楚起见,常量声明可以包含类型注释:
let greeting: String = "Hello"let numberOfToys: Int = 8let isMorning: Bool = true
常量是不可变的。它们的值不能改变:
let numberOfToys: Int = 8numberOfToys += 1// ❌ 错误:numberOfToys 不可变
import Foundationlet df = DateFormatter()df.dateFormat = "d MMMM yyyy"var birth = df.date(from: "5 June 1999")!var age: Int {Calendar.current.dateComponents([.year],from: birth,to: Date()).year!}print(age) // 20birth = df.date(from: "5 June 2002")!print(age) // 17
在下面的示例中,distanceInFeet 有一个 getter
和一个 setter
。 因为有 setter
,所以 getter
需要关键字 get
:
var distanceInMeters: Float = 100var distanceInFeet: Float {get {distanceInMeters * 3.28}set(newDistance) {distanceInMeters = newDistance / 3.28}}print(distanceInMeters) // 100.0print(distanceInFeet) // 328.0distanceInFeet = 250print(distanceInMeters) // 76.21951print(distanceInFeet) // 250.0distanceInMeters = 800print(distanceInMeters) // 800.0print(distanceInFeet) // 2624.0
var distance = 5 {willSet {print("距离将被设置")}}distance = 10 // 打印: 距离将被设置
可以在 willSet
中访问新值:
var distance = 5 {willSet(newDistance) {print("距离将被设置 \(newDistance)")}}distance = 10 // 打印: 距离将被设置 10
willSet
可用于在设置变量值之前执行一些代码
var distance = 5 {didSet {print("距离设置为 \(distance)")print("它的旧值是: \(oldValue)")}}distance = 10 // 打印: 距离将被设置 10// 打印: 它的旧值是:5
var distance = 5 {willSet(newDistance) {print("距离将设置为 \(newDistance)")}didSet {print("距离设置为 \(distance)")print("它的旧值是: \(oldValue)")}}distance = 10
var halloween = trueif halloween {print("不给糖就捣蛋!")}// 打印: 不给糖就捣蛋!if 5 > 3 {print("5 大于 3")} else {print("5 不超过 3")}// 输出: "5 大于 3"
var turbulence = falseif turbulence {print("请坐好。")} else {print("你可以自由地四处走动。")}// 打印: 你可以自由地四处走动。
var weather = "rainy"if weather == "sunny" {print("拿点防晒霜")} else if weather == "rainy" {print("拿一把雨伞")} else if weather == "snowing" {print("穿上你的雪地靴")} else {print("无效天气")}// 打印: 拿一把雨伞
5 > 1 // true6 < 10 // true2 >= 3 // false3 <= 5 // true"A" == "a" // false"B" != "b" // true
<
小于>
大于<=
小于或等于>=
大于或等于==
等于!=
不等于var driverLicense = truedriverLicense? print("驾驶座") : print("乘客座位")// 打印: 驾驶座
var secondaryColor = "green"switch secondaryColor {case "orange":print("红色和黄色的混合")case "purple":print("红色和蓝色的混合")case "green":print("蓝色和黄色的混合")default:print("这可能不是辅助颜色")}// 打印: 蓝色和黄色的混合
let year = 1905var artPeriod: Stringswitch year {case 1860...1885:artPeriod = "印象派"case 1886...1910:artPeriod = "后印象派"default:artPeriod = "未知"}// 打印: 后印象派
let service = "Seamless"switch service {case "Uber", "Lyft":print("旅行")case "DoorDash", "Seamless", "GrubHub":print("餐厅送餐")case "Instacart", "FreshDirect":print("杂货配送")default:print("未知服务")}// 打印: 餐厅外卖
let num = 7switch num {case let x where x % 2 == 0:print("\(num) 是偶数")case let x where x % 2 == 1:print("\(num) 奇数")default:print("\(num) 无效")}// 打印: 7 奇数
!true // false!false // true
true && true // truetrue && false // falsefalse && true // falsefalse && false // false
true || true // truetrue || false // truefalse || true // truefalse || false // false
!false && true || false // true
!false && true
首先计算并返回 true
然后,表达式,true
|| false
评估并返回最终结果 true
false || true && false // false
true && false
首先计算返回 false
然后,表达式,false
|| false
评估并返回最终结果 false
// 没有括号:true || true && false || false// ----> true// 带括号:(true || true) && (false || false)// ----> false
func greet(name: String?) {guard let unwrapped = name else {print("Hello guest!")return}print("Hello \(unwrapped)!")}greet(name: "Asma") // 输出:Hello Asma!greet(name: nil) // 输出:Hello guest!
let zeroToThree = 0...3// zeroToThree: 0, 1, 2, 3
for num in stride(from: 1, to: 5, by: 2) {print(num)}// 打印: 1// 打印: 3
for char in "hehe" {print(char)}// 打印: h// 打印: e// 打印: h// 打印: e
for num in 0...5 {if num % 2 == 0 {continue}print(num)}// 打印: 1// 打印: 3// 打印: 5
continue
关键字将强制循环继续进行下一次迭代
for char in "supercalifragilistice" {if char == "c" {break}print(char)}// 打印: s// 打印: u// 打印: p// 打印: e// 打印: r
for _ in 1...3 {print("Olé")}// 打印: Olé// 打印: Olé// 打印: Olé
for i in 0...10 {print(i) //0 到 10}
封闭指定范围操作符(...)
var counter = 1var stopNum = Int.random(in: 1...10)// 循环打印,直到满足停止条件while counter < stopNum {print(counter)counter += 1}
while
循环接受一个条件,并在所提供的条件为 true
时持续执行其主体代码。如果条件从不为假,则循环将继续运行,程序将陷入无限循环
var counter = 1repeat {print(counter)counter += 1} while counter <= 5
至少执行一次
// 创建一个字典var myDictionary = ["name": "John", "age": 25]// 使用for-in循环遍历字典for (key, value) in myDictionary {print("\(key): \(value)")}
var scores = [Int]()// 数组为空:[]
var grocery = ["🥓", "🥞", "🍪", "🥛", "🍊"]print(grocery.count)// 打印: 5
索引是指项目在有序列表中的位置,使用下标语法 array[index]
从数组中检索单个元素。
var vowels = ["a", "e", "i", "o", "u"]print(vowels[0]) // 打印: aprint(vowels[1]) // 打印: eprint(vowels[2]) // 打印: iprint(vowels[3]) // 打印: oprint(vowels[4]) // 打印: u
注意:Swift 数组是零索引的,这意味着第一个元素的索引为 0。
// 使用类型推断:var snowfall = [2.4, 3.6, 3.4, 1.8, 0.0]// 明确类型:var temp: [Int] = [33, 31, 30, 38, 44]
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 = ["小王", "张三", "王五"]for person in employees {print(person)}// 打印: 小王// 打印: 张三// 打印: 王五
var paintingsInMOMA: Set = ["The Dream","The Starry Night","The False Mirror"]
我们可以使用集合(Set
)来存储相同数据类型的唯一
元素
var team = Set<String>()print(team)// 打印: []
var vowels: Set = ["a", "e", "i", "o","u"]
要创建一个填充有值的集合,请在赋值运算符之前使用 Set
关键字。
var cookieJar: Set = ["Chocolate Chip","Oatmeal Raisin"]// 添加一个新元素cookieJar.insert("Peanut Butter Chip")
var oddNumbers: Set = [1, 2, 3, 5]// 移除现有元素oddNumbers.remove(2)// 删除所有元素oddNumbers.removeAll()
var names: Set = ["Rosa", "Doug", "Waldo"]print(names.contains("Lola")) //打印: falseif names.contains("Waldo"){print("There's Waldo!")} else {print("Where's Waldo?")}// 打印: There's Waldo!
var recipe: Set = ["蛋", "面粉", "糖"]for ingredient in recipe {print ("在配方中包含\(ingredient)")}
var emptySet = Set<String>()print(emptySet.isEmpty) // 打印: truevar populatedSet: Set = [1, 2, 3]print(populatedSet.isEmpty) // 打印: false
var band: Set = ["张三", "王五", "赵六"]print("乐队有 \(band.count) 名演奏者。")// 打印: 乐队有 4 名演奏者。
var setA: Set = ["A", "B", "C", "D"]var setB: Set = ["C", "D", "E", "F"]var setC = setA.intersection(setB)print(setC) // 打印: ["D", "C"]
var setA: Set = ["A", "B", "C", "D"]var setB: Set = ["C", "D", "E", "F"]var setC = setA.union(setB)print(setC)// 打印: ["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)// 打印: ["B", "E", "F", "A"]
var setA: Set = ["A", "B", "C", "D"]var setB: Set = ["C", "D"]var setC = setA.subtracting(setB)print(setC)// 打印: ["B", "A"]
var dictionaryName = ["Key1": "Value1","Key2": "Value2","Key3": "Value3"]
成对数据或键值对的无序
集合
var fruitStand = ["Coconuts": 12,"Pineapples": 12,"Papaya": 12]
每个键
都是唯一
的,即使它们都包含相同的值
var numberOfSides = ["triangle": 3,"square": 4,"rectangle": 4]
仅包含 String
键和 Int
值
var employeeID = ["Hamlet": 1367,"Horatio": 8261,"Ophelia": 9318]
// 初始化器语法:var yearlyFishPopulation = [Int: Int]()// 空字典字面量语法:var yearlyBirdPopulation: [Int: Int] = [:]
var pronunciation = ["library": "lai·breh·ree","apple": "a·pl"]// 新键:“programming”,新值:“prow·gra”pronunciation["programming"] = "prow·gra"
var bookShelf = ["Goodnight": "Margaret Wise Brown","The BFG": "Roald Dahl","Falling Up": "Shel Silverstein","No, David!": "David Shannon"]// 通过将 key 设置为 nil 来删除值bookShelf["The BFG"] = nil// 使用 .removeValue() 删除值bookShelf.removeValue(forKey: "Goodnight")// 删除所有值bookShelf.removeAll()
var change = ["Quarter": 0.29,"Dime": 0.15,"Nickel": 0.05]// 使用下标语法更改值change["Quarter"] = .25// 使用 .updateValue() 更改值change.updateValue(.10, forKey: "Dime")
要更改键值对的值,请使用 .updateValue()
方法或下标语法,通过将括号 [ ]
和其中的现有键附加到字典的名称,然后添加赋值运算符 (=
) 后跟修改后的值
var bakery = [String:Int]()// 检查字典是否为空print(bakery.isEmpty) // 打印 truebakery["Cupcakes"] = 12// 检查字典是否为空print(bakery.isEmpty) // 打印 false
var fruitStand = ["Apples": 12,"Oranges", 17]print(fruitStand.count) // 打印: 2
var hex = ["red": "#ff0000","yellow": "#ffff00","blue": "#0000ff",]print("蓝色十六进制代码 \(hex["blue"])")// 打印: 蓝色十六进制代码 Optional("#0000ff")if let redHex = hex["red"] {print("红色的十六进制代码 \(redHex)")}// 打印: 红色的十六进制代码 #ff0000
将键值对的值分配给变量将返回一个可选值。要提取值,请使用可选的展开
var emojiMeaning = ["🤔": "Thinking Face","😪": "Sleepy Face","😵": "Dizzy Face"]// 遍历键和值for (emoji, meaning) in emojiMeaning {print("\(emoji)被称为'\(meaning)Emoji'")}// 仅通过键迭代for emoji in emojiMeaning.keys {print(emoji)}// 仅通过值迭代for meaning in emojiMeaning.values {print(meaning)}
func washCar() -> Void {print("Soap")print("Scrub")print("Rinse")print("Dry")}
返回值为空的函数(void)
func greetLearner() {print("欢迎来到 Quick Reference!")}// 函数调用:greetLearner()// 打印: 欢迎来到 Quick Reference!
let birthYear = 1994var currentYear = 2020func findAge() -> Int {return currentYear - birthYear}print(findAge()) // 打印: 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)) // 打印: 2
func smartphoneModel() -> (name: String, version: String, yearReleased: Int) {return ("iPhone", "8 Plus", 2017)}let phone = smartphoneModel()print(phone.name) // 打印: iPhoneprint(phone.version) // 打印: 8 Plusprint(phone.yearReleased) // 打印: 2017
func findSquarePerimet(side: Int) -> Int {return side * 4}let perimeter = findSquarePerimet(side: 5)print(perimeter) // 打印: 20// Parameter: side// Argument: 5
func nextTotalSolarEclipse() -> String {"April 8th, 2024 🌎"}print(nextTotalSolarEclipse())// 打印: April 8th, 2024 🌎
func greet(person: String = "guest") {print("Hello \(person)")}greet() // Hello guestgreet(person: "Aliya") // Hello Aliya
var currentSeason = "冬天"func season(month:Int, name:inout String) {switch month {case 1...2:name = "冬天 ⛄️"case 3...6:name = "春天 🌱"case 7...9:name = "夏天 ⛱"case 10...11:name = "秋天 🍂"default:name = "未知"}}season(monthNum: 4, name: ¤tSeason)print(currentSeason) // 春天 🌱
func totalStudent(data: String...) -> Int {let numStudents = data.countreturn numStudents}print(totalStudent(data: "王五", "张三"))// 打印: 2
func getFirstInitial(from name: String?) -> String? {return name?.first}
函数可以接受可选类型并返回可选类型。当一个函数不能返回请求类型的合理实例时,它应该返回 nil
func multiply(x: Int, y: Int) -> Int {x * y}
func calculate(of numbers: Int...) -> Int {var sum = 0for number in numbers {sum += number}return sum}// 调用函数时,使用外部参数名let result = calculate(of: 1, 2, 3, 4, 5)print("Sum: \(result)")
func doMath(operation: (Int, Int) -> Int,a: Int, b: Int) -> Int {return operation(a, b)}// 定义一些可以作为参数传递的函数func add(_ a: Int, _ b: Int) -> Int {return a + b}// 使用 doMath 函数,并将 add 函数作为参数传递let result = doMath(5, 3, operation: add)print("Addition Result: \(result)")
let add: (Int, Int) -> Int = { (a, b) inreturn a + b}// 调用闭包let result = add(3, 5)print("Sum: \(result)")
struct Building {var address: Stringvar floors: Intinit(address: String, floors: Int) {self.address = addressself.floors = floors}}
结构或结构用于以编程方式在代码中表示现实生活中的对象。结构是使用 struct
关键字创建的,后跟其名称,然后是包含其属性和方法的主体
struct Car {var numOfWheels = 4var topSpeed = 80}var reliantRobin = Car(numOfWheels: 3)print(reliantRobin.numOfWheels) // 打印: 3print(reliantRobin.topSpeed) // 打印: 80
struct Person {var name: Stringvar age: Intinit(name: String, age: Int) {self.name = nameself.age = age}}// Person 实例:var morty = Person(name: "张三", age: 14)
struct TV {var size: Intvar type: Stringinit(size: Int, type: String) {self.size = sizeself.type = type}}
使用 TV
类
var newTV = TV(size: 65, type: "LED")
print(type(of: "abc")) // 打印: Stringprint(type(of: 123)) // 打印: 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)// 打印: ["Fries", "Burgers", "Toast"]
struct Dog {func bark() {print("Woof")}}let fido = Dog()fido.bark() // 打印: Woof
class Player {var name: Stringinit(name: String) {self.name = name}}var player1 = Player(name: "Tomoko")var player2 = player1player2.name = "Isabella"print(player1.name) // Isabellaprint(player2.name) // Isabella
class Person {var name = ""var age = 0}var sonny = Person()// sonny 现在是 Person 的一个实例
class Fruit {var hasSeeds = truevar color: Stringinit(color: String) {self.color = color}}
使用 Fruit 类
let apple = Fruit(color: "red")
可以使用 init()
方法和相应的初始化属性来初始化类,在 init()
方法中,self
关键字用于引用类分配属性值的实际实例
var ferris = Student()ferris.name = "Ferris Bueller"ferris.year = 12ferris.gpa = 3.81ferris.honors = false
假设我们有一个 BankAccount 类:
class BankAccount {var balance = 0.0func deposit(amount: Double) {balance += amount}func withdraw(amount: Double) {balance -= amount}}
SavingsAccount
继承 BankAccount
类
class SavingsAccount: BankAccount {var interest = 0.0func addInterest() {let interest = balance * 0.005self.deposit(amount: interest)}}
新的 SavingsAccount
类(子类)自动获得了 BankAccount
类(超类)的所有特征。 此外,SavingsAccount
类定义了一个 .interest
属性和一个 .addInterest()
方法。
使用数据类型
class Student {var name: Stringvar year: Intvar gpa: Doublevar honors: Bool}
使用默认属性值
class Student {var name = ""var gpa = 0.0var honors = false}
struct Resolution {var width = 0var height = 0}class VideoMode {var resolution = Resolution()var interlaced = falsevar frameRate = 0.0var name: String?}
Resolution
结构定义和 VideoMode
类定义仅描述 Resolution
或 VideoMode
的外观,创建结构或类的实例:
let resolution = Resolution(width: 1920)let someVideoMode = VideoMode()
extension String {var boolValue: Bool {return self == "1"}}let isTure = "0".boolValue
enum Day {case mondaycase tuesdaycase wednesdaycase thursdaycase fridaycase saturdaycase sunday}let casualWorkday: Day = .friday
enum Dessert {case cake(flavor: String)case vanillaIceCream(scoops: Int)case brownie}let custom: Dessert = .cake(flavor: "红色")switch custom {case let .cake(flavor):print("你点了一个 \(flavor) 蛋糕")case .brownie:print("你点了一块巧克力蛋糕")}// 打印: "你点了一个红色天鹅绒蛋糕"
enum Season: CaseIterable {case wintercase springcase summercase fall}for season in Season.allCases {print(season)}
添加对 CaseIterable
协议的一致性以访问 allCases
属性,该属性返回枚举的所有案例的数组
enum Beatle: String {case john, paul, george, ringo}print("披头士是 \(Beatle.john.rawValue).")// 打印: 披头士是 john.
enum Dessert {case cake(flavor: String)case vanillaIceCream(scoops: Int)case brownie}let order: Dessert = .cake(flavor: "红色")
enum Content {case emptycase text(String)case number(Int)}
使用 switch 处理可赋值枚举
let content = Content.text("Hello")switch content {case .empty:print("Value is empty")case .text(let value):print("Value is \(value)")case .number(_): //不调用时,可以省略print("Value is a number")}// 或者if case .text(let value) = content {print("Value is \(value)")}
enum Hello: String {case english = "Hello"case japanese = "你好呀!"case emoji = "👋"}let hello1 = Hello(rawValue: "你好呀!")let hello2 = Hello(rawValue: "Привет")print(hello1) // Optional(Hello.japanese)print(hello2) // nil
enum ShirtSize: String {case small = "S"case medium = "M"case large = "L"case extraLarge = "XL"var description: String {return "这件衬衫尺码是 \(self.rawValue)"}}
enum Currency: String {case euro = "EUR"case dollar = "USD"case pound = "GBP"}
输出枚举的原始值
let euroSymbol = Currency.euro.rawValueprint("欧元的货币符号是 \(euroSymbol)")
enum Traffic {case lightcase heavymutating func reportAccident() {self = .heavy}}
枚举也可以有实例方法
var currentTraffic: Traffic = .lightcurrentTraffic.reportAccident()// currentTraffic 现在是 .heavy
实例方法改变了枚举的值,则需要将其标记为 mutating
struct Person {var name: Stringvar age: Intfunc eat() {}}extension Person {// 添加新功能}extension Person: SomeProtocol {// 实现协议方法、属性}
// 给CGRect结构体提供允许center和size的构造器extension CGRect {init(center: CGPoint, size: CGSize) {let x: CGFloat = center.x - size.width * 0.5let y: CGFloat = center.y - size.height * 0.5self.init(origin: CGPoint(x: x, y: y),size: size)}}let frame = CGRect(center: CGPoint(x: 100, y: 100),size: CGSize(width: 50, height: 50))print("Origin is \(frame.origin)")
extension Double {mutating func cube() {self = self * self * self}}var boxCube: Double = 2.0boxCube.cube()print(boxCube)
extension String {func deletingPrefix(_ prefix: String) -> String {guard self.hasPrefix(prefix) else {return self}return String(self.dropFirst(prefix.count))}}print("Hello World".deletingPrefix("He"))
// 扩展可以添加计算属性,不能添加存储属性extension Double {var km: Double { self * 1000 }var m: Double { self }var cm: Double { self / 100.0 }var mm: Double { self / 1000.0 }}let metric: Double = 30.48.cmprint("1 metric is \(metric.m) meter")print("1 metric is \(metric.km) kilometer")
// 但可以通过 objc_getAssociatedObject/objc_setAssociatedObject 实现添加存储属性private var fuchsiaKey = "fuchsiaKey"extension UIColor {var fuchsia: UIColor? {get {return objc_getAssociatedObject(self, &fuchsiaKey) as? UIColor}set {objc_setAssociatedObject(self, &fuchsiaKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)}}}