├── examples ├── demo1.swift ├── demo16.swift ├── demo8.swift ├── demo10.swift ├── demo13.swift ├── demo2.swift ├── demo11.swift ├── demo3.swift ├── demo9.swift ├── demo14.swift ├── demo4.swift ├── demo18.swift ├── demo12.swift ├── demo15.swift ├── demo6.swift ├── demo17.swift ├── demo7.swift ├── demo5.swift ├── demo20.swift └── demo19.swift ├── .gitattributes ├── img └── collection_array_dictionary_comparison.png ├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── renovate.json ├── package.json ├── .gitignore ├── idoc.yml ├── swift.svg └── README.md /examples/demo1.swift: -------------------------------------------------------------------------------- 1 | print("Hello world!") 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.swift linguist-language=swift 2 | *.md linguist-detectable=true 3 | -------------------------------------------------------------------------------- /examples/demo16.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | var A = 42 3 | A = "This is hello" 4 | print(A) -------------------------------------------------------------------------------- /examples/demo8.swift: -------------------------------------------------------------------------------- 1 | var a = 86 2 | var b = a != 86 ? "歪果仁" : "中国人" 3 | print( b ) 4 | -------------------------------------------------------------------------------- /examples/demo10.swift: -------------------------------------------------------------------------------- 1 | var a = true 2 | var b = false 3 | print(!a) 4 | print(a && b) 5 | print(a || b) -------------------------------------------------------------------------------- /examples/demo13.swift: -------------------------------------------------------------------------------- 1 | var version :Int32 = 3 2 | var version2 :Int64 = 30 3 | 4 | print(version) 5 | print(version2) -------------------------------------------------------------------------------- /examples/demo2.swift: -------------------------------------------------------------------------------- 1 | let year = 1987 2 | var month = 11 3 | var day = 3 4 | 5 | print(year,month,day,separator:"-") -------------------------------------------------------------------------------- /examples/demo11.swift: -------------------------------------------------------------------------------- 1 | let constNumber: Int = 1987 2 | var name : String = "我是调调!" 3 | 4 | print(constNumber) 5 | print(name) -------------------------------------------------------------------------------- /examples/demo3.swift: -------------------------------------------------------------------------------- 1 | let constNumber = 1987 2 | var variableNumber = 13 3 | 4 | print(constNumber) 5 | print(variableNumber) -------------------------------------------------------------------------------- /examples/demo9.swift: -------------------------------------------------------------------------------- 1 | print("将输出 1 到 5") 2 | for i in 1...5 { 3 | print(i) 4 | } 5 | print("只输出 1 到 4") 6 | for i in 1..<5 { 7 | print(i) 8 | } -------------------------------------------------------------------------------- /img/collection_array_dictionary_comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaywcjlove/swift-tutorial/HEAD/img/collection_array_dictionary_comparison.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: jaywcjlove 2 | buy_me_a_coffee: jaywcjlove 3 | custom: ["https://www.paypal.me/kennyiseeyou", "https://jaywcjlove.github.io/#/sponsor"] 4 | -------------------------------------------------------------------------------- /examples/demo14.swift: -------------------------------------------------------------------------------- 1 | 2 | var stringArray: [String] = ["This", "is", "github"] 3 | 4 | // 并通过下面的方式可以访问数组和字典中的值 5 | print(stringArray[0]) // 访问第0个值, 数组的元素是从0开始记的 6 | -------------------------------------------------------------------------------- /examples/demo4.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * 这是一个错误的演示 3 | */ 4 | 5 | let constNumber = 1987 6 | var variableNumber = 13 7 | constNumber = variableNumber + 1 8 | print(constNumber) -------------------------------------------------------------------------------- /examples/demo18.swift: -------------------------------------------------------------------------------- 1 | let a: Int! = 5; 2 | // 表示可以承载一个 nil 3 | // 正常时不可以承载 nil 4 | 5 | let b = a // b 变成了显示可选性 `Int?` 6 | let e: Int = a 7 | let c: Int = a 8 | let d = a + 0 -------------------------------------------------------------------------------- /examples/demo12.swift: -------------------------------------------------------------------------------- 1 | var version = 3 2 | let tutorial = "Swift \(version) tutorial" 3 | let message = "Hello \(tutorial)!" 4 | var name = "Hello !" + "sdsd" 5 | print(tutorial) 6 | print(message) -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "packageRules": [ 6 | { 7 | "matchPackagePatterns": ["*"], 8 | "rangeStrategy": "replace" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/demo15.swift: -------------------------------------------------------------------------------- 1 | let awesome = ("Swift", 3, "awesome.") 2 | let (a, b, c) = awesome 3 | print(a) // 输出 Swift 4 | print(b) // 输出 3 5 | print(c) // 输出 awesome. 6 | 7 | 8 | // 和数组、字典不同的是,你不能通过[] 的方式来访问元组中的内容,但你可以像这样 9 | print(awesome.0) -------------------------------------------------------------------------------- /examples/demo6.swift: -------------------------------------------------------------------------------- 1 | print(1 + 2 + 3) // 输出 6 2 | print(15 - 3) // 输出 12 3 | print(23 * 3) // 输出 69 4 | print(100.0 / 2.5) // 输出 40.0 5 | print(90 % 4) // 输出 2 6 | print("Hello " + "Swift!") // 输出 Hello Swift! -------------------------------------------------------------------------------- /examples/demo17.swift: -------------------------------------------------------------------------------- 1 | // a 会被推测为 Int 类型 2 | let a = 42 3 | 4 | // pi 会被推测为 Double 类型 5 | let pi = 3.14159 6 | 7 | // anotherPi 会被推测为 Double 类型 8 | // 原始值3没有显式声明类型,而表达式中出现了一个浮点字面量, 9 | // 所以表达式会被推断为Double类型。 10 | let anotherPi = 3 + 0.14159 11 | 12 | print(anotherPi) 13 | -------------------------------------------------------------------------------- /examples/demo7.swift: -------------------------------------------------------------------------------- 1 | var example = 13 2 | 3 | print("输出结果:",example) 4 | example += 1 5 | print("输出结果:",example) 6 | example -= 1 7 | print("输出结果:",example) 8 | example *= 2 9 | print("输出结果:",example) 10 | example /= 1 11 | print("输出结果:",example) 12 | example %= 1 13 | print("输出结果:",example) -------------------------------------------------------------------------------- /examples/demo5.swift: -------------------------------------------------------------------------------- 1 | let constNumber = 1987 // 声明常量 constNumber 值为 1987 2 | var variableNumber = 13 // 声明变量 variableNumber 值为 13 3 | variableNumber = constNumber - 1 // 这里赋值,常量 constNumber 减 1 赋值给变量 variableNumber 4 | print(variableNumber) // 将 variableNumber 最终的值输出 -------------------------------------------------------------------------------- /examples/demo20.swift: -------------------------------------------------------------------------------- 1 | var optionalInteger: Int? 2 | optionalInteger = 404 3 | 4 | if optionalInteger != nil { // 确定可选类型包含值后可以在变量名后加!强制解析 5 | print(optionalInteger!) // 404 6 | } 7 | 8 | 9 | var errorCode: Int? = 404 // 在类型后面添加一个? 10 | print(errorCode) // Optional(404) 11 | errorCode = nil // 对非可选类型赋值为nil会报错 12 | print(errorCode) // nil 13 | 14 | // 确定可选类型包含值后可以在变量名后加!强制解析 15 | if errorCode != nil { 16 | print(errorCode!)// 404 17 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/package.json", 3 | "private": true, 4 | "name": "swift-tutorial", 5 | "title": "Swift 入门教程、读书笔记", 6 | "description": "通过简单的例子,来快速入门 Swift 语言基础编程、语法等各种语言特性,主要面向新手级别的学习者。", 7 | "version": "1.0.0", 8 | "scripts": { 9 | "start": "idoc --watch", 10 | "build": "idoc" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/jaywcjlove/swift-tutorial" 15 | }, 16 | "keywords": [ 17 | "swift", 18 | "tutorial", 19 | "swift-tutorial" 20 | ], 21 | "dependencies": { 22 | "idoc": "^1.29.0" 23 | } 24 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | .build/ 5 | *.pbxuser 6 | !default.pbxuser 7 | *.mode1v3 8 | !default.mode1v3 9 | *.mode2v3 10 | !default.mode2v3 11 | *.perspectivev3 12 | !default.perspectivev3 13 | xcuserdata 14 | *.xccheckout 15 | *.moved-aside 16 | DerivedData 17 | *.hmap 18 | *.ipa 19 | *.xcuserstate 20 | *.xcscmblueprint 21 | .DS_Store 22 | 23 | 24 | dist 25 | node_modules 26 | test/out 27 | 28 | npm-debug.log* 29 | lerna-debug.log 30 | yarn-error.log 31 | package-lock.json 32 | 33 | .DS_Store 34 | .cache 35 | .vscode 36 | .idea 37 | 38 | *.bak 39 | *.tem 40 | *.temp 41 | #.swp 42 | *.*~ 43 | ~*.* 44 | 45 | # IDEA 46 | *.iml 47 | *.ipr 48 | *.iws 49 | .idea/ -------------------------------------------------------------------------------- /examples/demo19.swift: -------------------------------------------------------------------------------- 1 | var ch: Character = "a" 2 | var emptyString = "" // 空字符串字面量 3 | var anotherEmptyString = String() // 初始化 String 实例 4 | // 两个字符串均为空并等价。 5 | // 通过检查其Boolean类型的isEmpty属性来判断该字符串是否为空 6 | if emptyString.isEmpty { 7 | print("什么都没有") 8 | } 9 | // 打印输出:"什么都没有" 10 | let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪" 11 | print("unusualMenagerie has \(unusualMenagerie.characters.count) characters") 12 | // 打印输出:"unusualMenagerie has 40 characters" 13 | 14 | // +相加在一起(或称“串联”) 15 | var str1 = "hello"; 16 | var str2 = " there"; 17 | var str = str1 + str2; 18 | print(str); 19 | // welcome 现在等于 "hello there" 20 | 21 | let normal = "Could you help me, please?" 22 | // 转化大写 23 | let shouty = normal.uppercased() 24 | // shouty 值为 "COULD YOU HELP ME, PLEASE?" 25 | // 转化小写 26 | let whispered = normal.lowercased() 27 | // whispered 值为 "could you help me, please?" -------------------------------------------------------------------------------- /idoc.yml: -------------------------------------------------------------------------------- 1 | site: Swift 入门教程、读书笔记 2 | favicon: ./swift.svg 3 | logo: ./swift.svg 4 | 5 | cacheFileStat: true 6 | 7 | homepage: https://wangchujiang.com/swift-tutorial/ 8 | 9 | menus: 10 | 首页: index.html 11 | 捐赠: 12 | url: https://wangchujiang.com/#/sponsor 13 | target: __blank 14 | 应用: 15 | url: https://wangchujiang.com/#/app 16 | target: __blank 17 | 18 | editButton: 19 | label: Edit this page on GitHub 20 | url: https://github.com/jaywcjlove/swift-tutorial/tree/master/ 21 | 22 | footer: | 23 | App • 24 | Projects • 25 | Sponsor • 26 | More Apps

27 | Released under the MIT License. Copyright © 2024 Kenny Wong
28 | Generated by idoc v{{idocVersion}} -------------------------------------------------------------------------------- /swift.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: actions/setup-node@v4 13 | with: 14 | node-version: 20 15 | registry-url: 'https://registry.npmjs.org' 16 | 17 | - run: npm install 18 | - run: npm run build 19 | 20 | - name: Generate Contributors Images 21 | uses: jaywcjlove/github-action-contributors@main 22 | with: 23 | filter-author: (renovate\[bot\]|renovate-bot|dependabot\[bot\]) 24 | output: dist/CONTRIBUTORS.svg 25 | avatarSize: 42 26 | 27 | - name: Create Tag 28 | id: create_tag 29 | uses: jaywcjlove/create-tag-action@main 30 | with: 31 | package-path: ./package.json 32 | 33 | - name: Deploy Website 34 | uses: peaceiris/actions-gh-pages@v4 35 | with: 36 | user_name: 'github-actions[bot]' 37 | user_email: 'github-actions[bot]@users.noreply.github.com' 38 | commit_message: ${{ github.event.head_commit.message }} 39 | github_token: ${{ secrets.GITHUB_TOKEN }} 40 | publish_dir: ./dist 41 | 42 | - name: Generate Changelog 43 | id: changelog 44 | uses: jaywcjlove/changelog-generator@main 45 | with: 46 | token: ${{ secrets.GITHUB_TOKEN }} 47 | filter-author: (jaywcjlove|小弟调调™|dependabot\[bot\]|Renovate Bot) 48 | filter: (^[\s]+?[R|r]elease)|(^[R|r]elease) 49 | 50 | - name: Create Release 51 | uses: ncipollo/release-action@v1 52 | if: steps.create_tag.outputs.successful 53 | with: 54 | allowUpdates: true 55 | token: ${{ secrets.GITHUB_TOKEN }} 56 | name: ${{ steps.create_tag.outputs.version }} 57 | tag: ${{ steps.create_tag.outputs.version }} 58 | body: | 59 | [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) 60 | 61 | Documentation ${{ steps.changelog.outputs.tag }}: https://raw.githack.com/jaywcjlove/vim-web/${{ steps.changelog.outputs.gh-pages-short-hash }}/index.html 62 | Comparing Changes: ${{ steps.changelog.outputs.compareurl }} 63 | 64 | ${{ steps.changelog.outputs.changelog }} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Swift入门教程、读书笔记 3 | === 4 | 5 | 6 | [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) 7 | [![CI](https://github.com/jaywcjlove/swift-tutorial/actions/workflows/ci.yml/badge.svg)](https://github.com/jaywcjlove/swift-tutorial/actions/workflows/ci.yml) 8 | 9 | 如果你已经掌握了一些 Swift 语法基础了,可以通过 [SwiftUI Example](https://github.com/jaywcjlove/swiftui-example) 来练习一些示例进行技术的提升。 10 | 11 | ✦ 欢迎下载我的 [macOS/iOS](https://wangchujiang.com/#app) 应用程序来支持我,谢谢 ✦ 12 | 13 |
14 | Vidwall 15 | Mousio Hint 16 | Mousio 17 | Musicer 18 | Audioer 19 | FileSentinel 20 | FocusCursor 21 | Videoer 22 | KeyClicker 23 | DayBar 24 | Iconed 25 | RightMenu Master 26 | Quick RSS 27 | Quick RSS 28 | Web Serve 29 | Copybook Generator 30 | DevTutor for SwiftUI 31 | RegexMate 32 | Time Passage 33 | Iconize Folder 34 | Textsound Saver 35 | Create Custom Symbols 36 | DevHub 37 | Resume Revise 38 | Palette Genius 39 | Symbol Scribe 40 |
41 | 42 |
43 | 欢迎下载 DevTutor,这是一款速查手册应用,旨在帮助开发者快速使用 SwiftUI 构建出色的应用程序。 44 |

45 |

46 | DevTutor for SwiftUI AppStore 47 | 48 |

49 | 50 | 51 | 52 | ## 示例目录 53 | 54 | - [准备环境](#准备环境) 55 | - [swiftc命令](#swiftc命令) 56 | - [print](#print) 57 | - [字符串拼接](#字符串拼接) 58 | - [注释](#注释) 59 | - [常量、变量](#常量变量) 60 | - [运算符](#运算符) 61 | - [数据类型](#数据类型) 62 | - [数值类型](#数值类型) 63 | - [数值范围](#数值范围) 64 | - [类型别名](#类型别名) 65 | - [类型安全](#类型安全) 66 | - [类型推断](#类型推断) 67 | - [元组和集合](#元组和集合) 68 | - [可选和隐式可选类型](#可选和隐式可选类型) 69 | - [可选类型](#可选类型) 70 | - [问题解决](#问题解决) 71 | - [工具](#工具) 72 | - [Web框架](#web框架) 73 | - [参考教程](#参考教程) 74 | 75 | 76 | 77 | ## 准备环境 78 | 79 | 在 Mac 上学习 Swift 非常简单,你只需在 App Store 中安装 [Xcode](https://itunes.apple.com/cn/app/xcode/id497799835) 即可。接下来,你有两种方法来学习 Swift 基础语法。 80 | 81 | **方法一:通过命令行** 82 | 83 | 你只需打开 Terminal 运行 swift 命令即可: 84 | 85 | ``` 86 | $ swift 87 | Welcome to Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1). Type :help for assistance. 88 | 1> var str = "Hello Siwft!" 89 | str: String = "Hello Siwft!" 90 | 2>:q //:q是推出命令 91 | ``` 92 | 93 | 运行 Swift 文件,在学习过程中,可以把一些存成 .swift 后缀的文件,通过 `swift filename.swift` 命令运行它输出结果。 94 | 95 | **方法二:通过Xcode运行** 96 | 97 | 打开 Xcode 软件,可以看到一个Xcode的欢迎界面,如果欢迎界面没有出来,你可以使用快捷键唤出 `⇧+⌘+1`(shift+command+1),在欢迎界面上可以看到 **Get started with a playground** 菜单,点击它建立一个 playground 的文件。我们可以在上面写代码,实时运行 swift 代码打印出运行结果。 98 | 99 | ## swiftc命令 100 | 101 | 上面通过swift运行程序,同时我们可以通过swiftc编译命令,编译成一个可执行的文件,直接运行可执行文件,遐想一下,感觉我们用swift可以干好多活儿。下面来运行一个 Hello World。 102 | 103 | 我们使用函数 print 来输出一个 Hello World 字符串。建立一个 [demo1.swift](examples/demo1.swift) 输入下面代码,放到了 examples 目录中: 104 | 105 | ``` 106 | print("Hello world!") 107 | ``` 108 | 109 | 将 examples 目录中的 [demo1.swift](examples/demo1.swift) 文件,编译出的可执行文件输出到 examples 目录中 文件名为 demo 110 | 111 | ``` 112 | swiftc examples/demo1.swift -o examples/demo 113 | ``` 114 | 115 | 通过 swift 运行 demo 并输出 Hello world!。 116 | 117 | ``` 118 | ./examples/demo 119 | ``` 120 | 121 | ## print 122 | 123 | 它是一个输出函数,在 [demo1.swift](examples/demo1.swift) 中我们使用过这个函数,现在建立 [demo1.swift](examples/demo1.swift) 文件,通过print函数输出多个值,使用 print的参数separator将分隔符自定义一下。例如: 124 | 125 | ```swift 126 | let year = 1987 127 | var month = 11 128 | var day = 3 129 | print(year,month,day,separator:"-") 130 | ``` 131 | 132 | 运行测试它,我们将看到输出结果: 133 | 134 | ``` 135 | $ swift examples/demo2.swift 136 | 1987-11-3 137 | ``` 138 | 139 | ## 字符串拼接 140 | 141 | 特别注意,在变量上面可以使用`+`来拼接字符串,常量拼接字符串会报错,常量和变量拼接同样报错。[demo12.swift](examples/demo12.swift) 142 | 143 | ```swift 144 | var version = 3 145 | let tutorial = "Swift \(version) tutorial" 146 | let message = "Hello \(tutorial)!" 147 | var name = "Hello !" + "sdsd" 148 | print(tutorial) 149 | print(message) 150 | ``` 151 | 152 | ## 注释 153 | 154 | Swift注释与JS注释一样。 155 | 156 | 段落注释 157 | 158 | ```swift 159 | /* 160 | 这里是段落注释 161 | */ 162 | ``` 163 | 164 | 单行注释 165 | 166 | ```swift 167 | // 这里是单行注释 168 | ``` 169 | 170 | ## 常量、变量 171 | 172 | - let常量,不能更改的值(immutable) 173 | - var变量,可以更改的值(mutable) 174 | 175 | 声明一个名字叫做 constNumber 的常量,并给它一个值 1987 ,声明一个名字叫做 variableNumber 的变量,并给它一个值为 13,分别输出 constNumber 和 variableNumber 的值,将它保存到 [demo3.swift](examples/demo3.swift) 中: 176 | 177 | ```swift 178 | let constNumber = 1987 179 | var variableNumber = 13 180 | 181 | print(constNumber) 182 | print(variableNumber) 183 | ``` 184 | 185 | 运行测试它,我们将看到输出结果: 186 | 187 | ``` 188 | $ swift examples/demo3.swift 189 | 1987 190 | 13 191 | ``` 192 | 193 | 通过上面的例子,我们来测试一下常量和变量的特性,下面代码保存到 [demo4.swift](examples/demo4.swift) 文件中 194 | 195 | ```swift 196 | let constNumber = 1987 197 | var variableNumber = 13 198 | constNumber = variableNumber + 1 199 | print(constNumber) 200 | ``` 201 | 202 | 上面这个错误的例子是,将变量 variableNumber 加 1 赋值给常量 constNumber。这是一个错误的演示,它运行会曝出错误信息,如果你使用 Xcode 将自动有个错误提示,你只需直接点击错误信息就可以自动修改错误,好智能的功能哦。 203 | 204 | ``` 205 | $ swift examples/demo4.swift 206 | examples/demo4.swift:4:13: error: cannot assign to value: 'constNumber' is a 'let' constant 207 | constNumber = variableNumber + 1 208 | ~~~~~~~~~~~ ^ 209 | examples/demo4.swift:1:1: note: change 'let' to 'var' to make it mutable 210 | let constNumber = 1987 211 | ^~~ 212 | var 213 | ``` 214 | 215 | ## 运算符 216 | 217 | 用来做运算的,上面例子已经使用了运算符 `-`,其实就是跟数学运算是一样的 218 | 219 | - 加`+` 220 | - 减`-` 221 | - 乘`*` 222 | - 除`/` 223 | - 求余`%` 224 | - 相等`==` 225 | - 不等于`a != b` 226 | - 大于`a > b` 227 | - 小于`a < b` 228 | - 大于等于`a >= b` 229 | - 小于等于`a <= b` 230 | 231 | **赋值运算符** [demo5.swift](examples/demo5.swift) 232 | 233 | ```swift 234 | let constNumber = 1987 // 声明常量 constNumber 值为 1987 235 | var variableNumber = 13 // 声明变量 variableNumber 值为 13 236 | variableNumber = constNumber - 1 // 这里赋值,常量 constNumber 减 1 赋值给变量 variableNumber 237 | print(variableNumber) // 将 variableNumber 最终的值输出 238 | ``` 239 | 240 | 运行结果 241 | 242 | ```bash 243 | $ swift examples/demo5.swift 244 | 1986 245 | ``` 246 | 247 | **算数运算符** [demo6.swift](examples/demo6.swift) 248 | 249 | 算数运算符也就是我们常见到的数学运算了,加`+`、 减`-`、 乘`*`、 除`/`、 求余`%`。 250 | 251 | ```swift 252 | print(1 + 2 + 3) // 输出 6 253 | print(15 - 3) // 输出 12 254 | print(23 * 3) // 输出 69 255 | print(100.0 / 2.5) // 输出 40.0 256 | print(90 % 4) // 输出 2 257 | print("Hello " + "Swift!") // 输出 Hello Swift! 258 | ``` 259 | 260 | 运行结果 261 | 262 | ```bash 263 | $ swift examples/demo6.swift 264 | 6 265 | 12 266 | 69 267 | 40.0 268 | 2 269 | Hello Swift! 270 | ``` 271 | 272 | **组合赋值运算符** 273 | 274 | 比如下面这样的代码,我们完全可以使用组合赋值运算符简写。 275 | 276 | ```swift 277 | var variableNumber = 13 278 | 279 | // 这句是可以使用组合赋值运算符简写 280 | variableNumber = variableNumber + 1 281 | 282 | // 简写 283 | variableNumber += 1 284 | ``` 285 | 286 | 来个各种合赋值运算符例子 [demo7.swift](examples/demo7.swift) 287 | 288 | ```swift 289 | var example = 13 290 | 291 | print("输出结果:",example) 292 | example += 1 293 | print("输出结果:",example) 294 | example -= 1 295 | print("输出结果:",example) 296 | example *= 2 297 | print("输出结果:",example) 298 | example /= 1 299 | print("输出结果:",example) 300 | example %= 1 301 | print("输出结果:",example) 302 | ``` 303 | 304 | **比较运算符** 305 | 306 | 可以通过 相等`==`、 不等于`a != b`、 大于`a > b`、 小于`a < b`、 大于等于`a >= b`、 小于等于`a <= b`进行比较运算。 307 | 308 | 例如:`print(12 != 1)` 将会返回一个布尔值 ture 309 | 310 | 311 | **三目运算符**[demo8.swift](examples/demo8.swift) 312 | 313 | 三目运算符也就是三元运算符 `判断条件 ? 答案 1 : 答案 2` 314 | 315 | ```swift 316 | var a = 86 317 | var b = a != 86 ? "歪果仁" : "中国人" 318 | print( b ) 319 | ``` 320 | 321 | **区间运算符** 322 | 323 | - 闭区间运算符(`a...b`)定义一个包含从 a 到 b(包括 a 和 b)的所有值的区间。a 的值不能超过 b。 324 | - 半开区间(`a.. (Int) 377 | 378 | 一般来说,你不需要专门指定整数的长度。Swift 提供了一个特殊的整数类型Int,长度与当前平台的原生字长相同[demo13.swift](examples/demo13.swift): 379 | 380 | - 在32位平台上,Int和Int32长度相同。 381 | - 在64位平台上,Int和Int64长度相同。 382 | 383 | ```swift 384 | var version :Int32 = 3 385 | var version2 :Int64 = 30 386 | 387 | print(version) 388 | print(version2) 389 | ``` 390 | 391 | **浮点数** 392 | 393 | - Double表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。 394 | - Float表示32位浮点数。精度要求不高的话可以使用此类型。 395 | 396 | > 注意: 397 | > Double精确度很高,至少有15位数字,而Float最少只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围。 398 | 399 | **无符号类型** 400 | 401 | > (UInt) 402 | 403 | Swift 也提供了一个特殊的无符号类型UInt。 404 | 405 | > 注意: 406 | > 尽量不要使用UInt,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。除了这种情况,最好使用Int,即使你要存储的值已知是非负的。统一使用Int可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推断。 407 | 408 | 409 | **布尔类型** 410 | 411 | > (Bool) 412 | 413 | Swift 有一个基本的布尔(Boolean)类型,叫做Bool。布尔值指逻辑上的值,因为它们只能是真或者假。Swift 有两个布尔常量,true和false。 414 | 415 | **字符和字符串类型** 416 | 417 | > (Character/String) 418 | 419 | 只包含一个字符的时候,我们也可以把它作为字符类型,Character 只是 String 的一种特殊情况,一般来说,我们都使用 String 就好了[demo19.swift](examples/demo19.swift): 420 | 421 | ```swift 422 | var ch: Character = "a" 423 | var emptyString = "" // 空字符串字面量 424 | var anotherEmptyString = String() // 初始化 String 实例 425 | // 两个字符串均为空并等价。 426 | // 通过检查其Boolean类型的isEmpty属性来判断该字符串是否为空 427 | if emptyString.isEmpty { 428 | print("什么都没有") 429 | } 430 | // 打印输出:"什么都没有" 431 | let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪" 432 | print("unusualMenagerie has \(unusualMenagerie.characters.count) characters") 433 | // 打印输出:"unusualMenagerie has 40 characters" 434 | 435 | // +相加在一起(或称“串联”) 436 | var str1 = "hello"; 437 | var str2 = " there"; 438 | var str = str1 + str2; 439 | print(str); 440 | // welcome 现在等于 "hello there" 441 | 442 | let normal = "Could you help me, please?" 443 | // 转化大写 444 | let shouty = normal.uppercaseString 445 | // shouty 值为 "COULD YOU HELP ME, PLEASE?" 446 | // 转化小写 447 | let whispered = normal.lowercaseString 448 | // whispered 值为 "could you help me, please?" 449 | ``` 450 | 451 | - 一个字符串中并不一定占用相同的内存空间 452 | 453 | 字符串常量可以包括下面这些特殊字符: 454 | 455 | - 空字符`\0`,反斜杠`\`,制表符`\t`,换行符`\n`,回车符`\r`,双引号`\"`和单引号`\'` 456 | - 单字节Unicode字符,`\xnn`,其中nn是两个十六进制数 457 | - 双字节Unicode字符,`\unnnn`,其中nnnn是四个十六进制数 458 | - 四字节Unicode字符,`\Unnnnnnnn`,其中nnnnnnnn是八个十六进制数 459 | 460 | 461 | **数组和字典** 462 | 463 | 数组和字典是两种非常长常见的数据类型,在刚才介绍的类型中,一个量通常只能包含一个值。而数组这种类型,就可以容纳相同类型的的多个值;而字典这种类型,可以容纳多个对应关系(一个值唯一对应另一个值) 464 | 465 | ```swift 466 | var stringArray: [String] = ["This", "is", "github"] 467 | 468 | // 并通过下面的方式可以访问数组和字典中的值 469 | print(stringArray[0]) // 访问第0个值, 数组的元素是从0开始记的 470 | ``` 471 | 472 | ### 数值范围 473 | 474 | 下表显示了不同变量类型内存的存储空间,及变量类型的最大最小值: 475 | 476 | | 类型 | 大小(字节) | 区间值 | 477 | | ---- | ---- | ---- | 478 | | Int8 | 1 字节 | -127 到 127 | 479 | | UInt8 | 1 字节 | 0 到 255 | 480 | | Int32 | 4 字节 | -2147483648 到 2147483647 | 481 | | UInt32 | 4 字节 | 0 到 4294967295 | 482 | | Int64 | 8 字节 | -9223372036854775808 到 9223372036854775807 | 483 | | UInt64 | 8 字节 | 0 到 18446744073709551615 | 484 | | Float | 4 字节 | 1.2E-38 到 3.4E+38 (~6 digits) | 485 | | Double | 8 字节 | 2.3E-308 到 1.7E+308 (~15 digits) | 486 | 487 | ### 类型别名 488 | 489 | 类型别名对当前的类型定义了另一个名字,类型别名通过使用 typealias 关键字来定义。语法格式如下: 490 | 491 | > typealias 类型名字 = type 492 | 493 | ```swift 494 | // 例如以下定义了 Int 的类型别名为 Feet: 495 | typealias Feet = Int 496 | 497 | // 由于前面已经定义了类型别名,那么这里使用Feet也相当于使用Int 498 | // 所以AudioSample.min = Int.min,也就是0. 499 | var maxAmplitudeFound = Feet.min; 500 | // 几面输出 maxAmplitudeFound: Int = -9223372036854775808 501 | 502 | // 现在,我们可以通过别名来定义变量: 503 | typealias:Feet = Intvar 504 | distance: Feet = 100 505 | print(distance) 506 | // 我们使用 playground 执行以上程序,输出结果为: 507 | // 100· 508 | ``` 509 | 510 | ### 类型安全 511 | 512 | Swift 是一个类型安全(type safe)的语言。由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。[demo16.swift](examples/demo16.swift) 513 | 514 | ```swift 515 | import Cocoa 516 | var A = 42 517 | A = "This is hello" 518 | print(A) 519 | ``` 520 | 521 | ```bash 522 | $ swift examples/demo16.swift 523 | examples/demo16.swift:3:5: error: cannot assign value of type 'String' to type 'Int' 524 | A = "This is hello" 525 | ^~~~~~~~~~~~~~~ 526 | ``` 527 | 528 | ### 类型推断 529 | 530 | 如果你没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。[demo17.swift](examples/demo17.swift) 531 | 532 | ```swift 533 | // a 会被推测为 Int 类型 534 | let a = 42 535 | 536 | // pi 会被推测为 Double 类型 537 | let pi = 3.14159 538 | 539 | // anotherPi 会被推测为 Double 类型 540 | // 原始值3没有显式声明类型,而表达式中出现了一个浮点字面量, 541 | // 所以表达式会被推断为Double类型。 542 | let anotherPi = 3 + 0.14159 543 | 544 | print(anotherPi) 545 | //上面输出 3.14159 546 | ``` 547 | 548 | ### 元组和集合 549 | 550 | 元组不是一种类型,但是却是一种可以表示数据的结构。数组保存多个相同类型的值,而元组则可以保存多个不同类型的值,它的用法如下[demo15.swift](examples/demo15.swift): 551 | 552 | ```swift 553 | let awesome = ("Swift", 3, "awesome.") 554 | let (a, b, c) = awesome 555 | print(a) // 输出 Swift 556 | print(b) // 输出 3 557 | print(c) // 输出 awesome. 558 | 559 | // 和数组、字典不同的是,你不能通过[] 的方式来访问元组中的内容,但你可以像这样 560 | print(awesome.0) 561 | ``` 562 | 563 | 集合的声明和数组非常类似,都是通过 [] 进行,不同的地方在于集合只能容纳不同的值,而数组可以容纳相同的值: 564 | 565 | ```swift 566 | let sets: Set = [1, 2, 3, 4] 567 | let arrays: Array = [1, 1, 1, 1] 568 | ``` 569 | 570 | 上面定义了 sets 是一个 Set 集合类型,容纳的是 Int 类型的值,数组同理 571 | 572 | 默认情况下,如果你不做显式声明,Swift 会默认将其推断为数组类型 573 | 关于集合、数组、字典之间的关系,下面这张图很好的展示了这一切:[画图工具](http://asciiflow.com/) 574 | 575 | ```bash 576 | Array Set Dictionary 577 | ┏--------------┓ ┏---------------┓ ┏-------------------------┓ 578 | ┆ Index Value ¦ ¦ Value ¦ ¦ Keys Values ¦ 579 | ¦ ┌---┬------┐ ¦ ¦ ¦ ¦ ┌----┐ ┌-------┐ ¦ 580 | ¦ ¦0 ¦Six ¦ ¦ ¦ ┌----┐ ¦ ¦ ¦YYZ ├-------▷¦Toronto¦ ¦ 581 | ¦ ├---┼------┤ ¦ ¦ ¦Rock¦ ┌----┐ ¦ ¦ ├----┤ └-------┘ ¦ 582 | ¦ ¦1 ¦Milk ¦ ¦ ¦ └----┘ ¦Jazz¦ ¦ ¦ ¦DUB ├---┐ ¦ 583 | ¦ ├---┼------┤ ¦ ¦ └----┘ ¦ ¦ ├----┤ ¦ ┌-------┐ ¦ 584 | ¦ ¦2 ¦Flour ¦ ¦ ¦ ┌-----┐ ¦ ¦ ¦LHR ├---┼---▷¦London ¦ ¦ 585 | ¦ ├---┼------┤ ¦ ¦ ¦Class¦ ┌---┐ ¦ ¦ └----┘ ¦ └-------┘ ¦ 586 | ¦ ¦3 ¦Powder¦ ¦ ¦ └-----┘ ¦Cat¦ ¦ ¦ ¦ ¦ 587 | ¦ ├---┼------┤ ¦ ¦ └---┘ ¦ ¦ ¦ ┌-------┐ ¦ 588 | ¦ ¦4 ¦Hello ¦ ¦ ¦ ¦ ¦ └---▷¦Dubin ¦ ¦ 589 | ¦ └---┴------┘ ¦ ¦ ¦ ¦ └-------┘ ¦ 590 | ┗--------------┛ ┗---------------┛ ┗-------------------------┛ 591 | ``` 592 | 593 | ## 可选和隐式可选类型 594 | 595 | - 类型后面用问号 `?` 表示可选类型; 596 | - 类型后面用感叹号 `!` 表示隐式可选类型; 597 | 598 | ### 可选类型 599 | 600 | 当基础类型(整形、浮点、布尔等)没有值时,是不能使用的。Swift 为了表达这种状态,对类型提供了可选的概念。在某个类型后面添加 ? 可以表示一个可选类型,这个可选类型有两种状态:1. 有值;2. 没值 601 | 602 | ```swift 603 | var optionalInteger: Int? 604 | optionalInteger = 404 605 | 606 | if optionalInteger != nil { // 确定可选类型包含值后可以在变量名后加!强制解析 607 | print(optionalInteger!) // 404 608 | } 609 | 610 | var errorCode: Int? = 404 // 在类型后面添加一个? 611 | print(errorCode) // Optional(404) // 会打印警告 612 | errorCode = nil // 对非可选类型赋值为nil会报错 613 | print(errorCode) // nil // 会打印警告 614 | 615 | // 确定可选类型包含值后可以在变量名后加!强制解析 616 | if errorCode != nil { 617 | print(errorCode!)// 404 618 | } 619 | ``` 620 | 621 | ## 问题解决 622 | 623 | - [swift NameError: name 'run_one_line' is not defined](https://github.com/Homebrew/homebrew-core/issues/2712) 624 | 625 | ## 工具 626 | 627 | - [Carthage](https://github.com/Carthage/Carthage) 一个简单的,分散的Cocoa依赖管理器 628 | - [CocoaPods](https://github.com/CocoaPods/CocoaPods) Swift和Objective-C Cocoa项目的依赖管理器。 629 | 630 | ## Web框架 631 | 632 | - [apple/swift-nio](https://github.com/apple/swift-nio) 633 | - [Vapor](https://github.com/vapor/vapor) 634 | - [Perfect](https://github.com/PerfectlySoft/Perfect) 635 | - [Kitura](https://github.com/IBM-Swift/Kitura) 636 | - [Zewo](https://github.com/Zewo/Zewo) 637 | - [Smoke](https://github.com/amzn/smoke-framework) 638 | 639 | ## 参考教程 640 | 641 | - [The Swift Programming Language 中文版](http://special.csdncms.csdn.net/the-swift-programming-language-in-chinese/Introduction.shtml) 642 | - [官方文档The Swift Programming Language](https://swift.org/documentation/#the-swift-programming-language) 643 | - [官方文档的中文版The Swift Programming Language中文版](https://github.com/numbbbbb/the-swift-programming-language-in-chinese) 644 | - [Swift3.0语法速查手册](https://darielchen.github.io/SwiftManual/) 645 | - [戴铭的 Swift 小册子](https://ming1016.github.io/2021/11/23/daiming-swift-pamphlet/) 646 | - [探索函数式编程和 Swift 的视频系列](https://github.com/pointfreeco/episode-code-samples) 647 | - [SwiftUI 相关文章](https://serialcoder.dev/category/text-tutorials/swiftui/) 648 | - [深入浅出 Swift 3](https://www.shiyanlou.com/courses/611) 649 | - [Swift教程](http://c.biancheng.net/cpp/swift/jiaocheng/) 650 | - [慕课网Swift教程](http://www.imooc.com/search/course?words=swift) 651 | - [Swift 必备 tips](http://swifter.tips) 652 | - [Swift 学习指引](http://www.swiftguide.cn) 653 | - [swiftcafe](http://swiftcafe.io) 654 | - [SwiftGG](http://swift.gg) 655 | - [swiftweekly](http://swiftweekly.cn) 656 | - [dianqk](http://blog.dianqk.org) 657 | 658 | ## Contributors 659 | 660 | As always, thanks to our amazing contributors! 661 | 662 | 663 | 664 | 665 | 666 | Made with [action-contributors](https://github.com/jaywcjlove/github-action-contributors). 667 | 668 | ## License 669 | 670 | Licensed under the MIT License. 671 | --------------------------------------------------------------------------------