Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jaywcjlove/swift-tutorial
Swift入门教程、读书笔记
https://github.com/jaywcjlove/swift-tutorial
ios swift swift5 swiftui
Last synced: 6 days ago
JSON representation
Swift入门教程、读书笔记
- Host: GitHub
- URL: https://github.com/jaywcjlove/swift-tutorial
- Owner: jaywcjlove
- Created: 2016-12-16T05:55:34.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2024-10-07T22:00:56.000Z (4 months ago)
- Last Synced: 2024-10-29T10:38:48.694Z (3 months ago)
- Topics: ios, swift, swift5, swiftui
- Homepage: https://jaywcjlove.github.io/swift-tutorial
- Size: 320 KB
- Stars: 105
- Watchers: 5
- Forks: 17
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
Swift入门教程、读书笔记
===[![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor)
[![CI](https://github.com/jaywcjlove/swift-tutorial/actions/workflows/ci.yml/badge.svg)](https://github.com/jaywcjlove/swift-tutorial/actions/workflows/ci.yml)如果你已经掌握了一些 Swift 语法基础了,可以通过 [SwiftUI Example](https://github.com/jaywcjlove/swiftui-example) 来练习一些示例进行技术的提升。
✦ 欢迎下载我的 [macOS/iOS](https://wangchujiang.com/#app) 应用程序来支持我,谢谢 ✦
## 示例目录
- [准备环境](#准备环境)
- [swiftc命令](#swiftc命令)
- [print](#print)
- [字符串拼接](#字符串拼接)
- [注释](#注释)
- [常量、变量](#常量变量)
- [运算符](#运算符)
- [数据类型](#数据类型)
- [数值类型](#数值类型)
- [数值范围](#数值范围)
- [类型别名](#类型别名)
- [类型安全](#类型安全)
- [类型推断](#类型推断)
- [元组和集合](#元组和集合)
- [可选和隐式可选类型](#可选和隐式可选类型)
- [可选类型](#可选类型)
- [问题解决](#问题解决)
- [工具](#工具)
- [Web框架](#web框架)
- [参考教程](#参考教程)## 准备环境
在 Mac 上学习 Swift 非常简单,你只需在 App Store 中安装 [Xcode](https://itunes.apple.com/cn/app/xcode/id497799835) 即可。接下来,你有两种方法来学习 Swift 基础语法。
**方法一:通过命令行**
你只需打开 Terminal 运行 swift 命令即可:
```
$ swift
Welcome to Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1). Type :help for assistance.
1> var str = "Hello Siwft!"
str: String = "Hello Siwft!"
2>:q //:q是推出命令
```运行 Swift 文件,在学习过程中,可以把一些存成 .swift 后缀的文件,通过 `swift filename.swift` 命令运行它输出结果。
**方法二:通过Xcode运行**
打开 Xcode 软件,可以看到一个Xcode的欢迎界面,如果欢迎界面没有出来,你可以使用快捷键唤出 `⇧+⌘+1`(shift+command+1),在欢迎界面上可以看到 **Get started with a playground** 菜单,点击它建立一个 playground 的文件。我们可以在上面写代码,实时运行 swift 代码打印出运行结果。
## swiftc命令
上面通过swift运行程序,同时我们可以通过swiftc编译命令,编译成一个可执行的文件,直接运行可执行文件,遐想一下,感觉我们用swift可以干好多活儿。下面来运行一个 Hello World。
我们使用函数 print 来输出一个 Hello World 字符串。建立一个 [demo1.swift](examples/demo1.swift) 输入下面代码,放到了 examples 目录中:
```
print("Hello world!")
```
将 examples 目录中的 [demo1.swift](examples/demo1.swift) 文件,编译出的可执行文件输出到 examples 目录中 文件名为 demo```
swiftc examples/demo1.swift -o examples/demo
```通过 swift 运行 demo 并输出 Hello world!。
```
./examples/demo
```它是一个输出函数,在 [demo1.swift](examples/demo1.swift) 中我们使用过这个函数,现在建立 [demo1.swift](examples/demo1.swift) 文件,通过print函数输出多个值,使用 print的参数separator将分隔符自定义一下。例如:
```swift
let year = 1987
var month = 11
var day = 3
print(year,month,day,separator:"-")
```运行测试它,我们将看到输出结果:
```
$ swift examples/demo2.swift
1987-11-3
```## 字符串拼接
特别注意,在变量上面可以使用`+`来拼接字符串,常量拼接字符串会报错,常量和变量拼接同样报错。[demo12.swift](examples/demo12.swift)
```swift
var version = 3
let tutorial = "Swift \(version) tutorial"
let message = "Hello \(tutorial)!"
var name = "Hello !" + "sdsd"
print(tutorial)
print(message)
```## 注释
Swift注释与JS注释一样。
段落注释
```swift
/*
这里是段落注释
*/
```单行注释
```swift
// 这里是单行注释
```## 常量、变量
- let常量,不能更改的值(immutable)
- var变量,可以更改的值(mutable)声明一个名字叫做 constNumber 的常量,并给它一个值 1987 ,声明一个名字叫做 variableNumber 的变量,并给它一个值为 13,分别输出 constNumber 和 variableNumber 的值,将它保存到 [demo3.swift](examples/demo3.swift) 中:
```swift
let constNumber = 1987
var variableNumber = 13print(constNumber)
print(variableNumber)
```运行测试它,我们将看到输出结果:
```
$ swift examples/demo3.swift
1987
13
```通过上面的例子,我们来测试一下常量和变量的特性,下面代码保存到 [demo4.swift](examples/demo4.swift) 文件中
```swift
let constNumber = 1987
var variableNumber = 13
constNumber = variableNumber + 1
print(constNumber)
```上面这个错误的例子是,将变量 variableNumber 加 1 赋值给常量 constNumber。这是一个错误的演示,它运行会曝出错误信息,如果你使用 Xcode 将自动有个错误提示,你只需直接点击错误信息就可以自动修改错误,好智能的功能哦。
```
$ swift examples/demo4.swift
examples/demo4.swift:4:13: error: cannot assign to value: 'constNumber' is a 'let' constant
constNumber = variableNumber + 1
~~~~~~~~~~~ ^
examples/demo4.swift:1:1: note: change 'let' to 'var' to make it mutable
let constNumber = 1987
^~~
var
```## 运算符
用来做运算的,上面例子已经使用了运算符 `-`,其实就是跟数学运算是一样的
- 加`+`
- 减`-`
- 乘`*`
- 除`/`
- 求余`%`
- 相等`==`
- 不等于`a != b`
- 大于`a > b`
- 小于`a < b`
- 大于等于`a >= b`
- 小于等于`a <= b`**赋值运算符** [demo5.swift](examples/demo5.swift)
```swift
let constNumber = 1987 // 声明常量 constNumber 值为 1987
var variableNumber = 13 // 声明变量 variableNumber 值为 13
variableNumber = constNumber - 1 // 这里赋值,常量 constNumber 减 1 赋值给变量 variableNumber
print(variableNumber) // 将 variableNumber 最终的值输出
```运行结果
```bash
$ swift examples/demo5.swift
1986
```**算数运算符** [demo6.swift](examples/demo6.swift)
算数运算符也就是我们常见到的数学运算了,加`+`、 减`-`、 乘`*`、 除`/`、 求余`%`。
```swift
print(1 + 2 + 3) // 输出 6
print(15 - 3) // 输出 12
print(23 * 3) // 输出 69
print(100.0 / 2.5) // 输出 40.0
print(90 % 4) // 输出 2
print("Hello " + "Swift!") // 输出 Hello Swift!
```运行结果
```bash
$ swift examples/demo6.swift
6
12
69
40.0
2
Hello Swift!
```**组合赋值运算符**
比如下面这样的代码,我们完全可以使用组合赋值运算符简写。
```swift
var variableNumber = 13// 这句是可以使用组合赋值运算符简写
variableNumber = variableNumber + 1// 简写
variableNumber += 1
```来个各种合赋值运算符例子 [demo7.swift](examples/demo7.swift)
```swift
var example = 13print("输出结果:",example)
example += 1
print("输出结果:",example)
example -= 1
print("输出结果:",example)
example *= 2
print("输出结果:",example)
example /= 1
print("输出结果:",example)
example %= 1
print("输出结果:",example)
```**比较运算符**
可以通过 相等`==`、 不等于`a != b`、 大于`a > b`、 小于`a < b`、 大于等于`a >= b`、 小于等于`a <= b`进行比较运算。
例如:`print(12 != 1)` 将会返回一个布尔值 ture
**三目运算符**[demo8.swift](examples/demo8.swift)
三目运算符也就是三元运算符 `判断条件 ? 答案 1 : 答案 2`
```swift
var a = 86
var b = a != 86 ? "歪果仁" : "中国人"
print( b )
```**区间运算符**
- 闭区间运算符(`a...b`)定义一个包含从 a 到 b(包括 a 和 b)的所有值的区间。a 的值不能超过 b。
- 半开区间(`a.. (Int)一般来说,你不需要专门指定整数的长度。Swift 提供了一个特殊的整数类型Int,长度与当前平台的原生字长相同[demo13.swift](examples/demo13.swift):
- 在32位平台上,Int和Int32长度相同。
- 在64位平台上,Int和Int64长度相同。```swift
var version :Int32 = 3
var version2 :Int64 = 30print(version)
print(version2)
```**浮点数**
- Double表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。
- Float表示32位浮点数。精度要求不高的话可以使用此类型。> 注意:
> Double精确度很高,至少有15位数字,而Float最少只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围。**无符号类型**
> (UInt)
Swift 也提供了一个特殊的无符号类型UInt。
> 注意:
> 尽量不要使用UInt,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。除了这种情况,最好使用Int,即使你要存储的值已知是非负的。统一使用Int可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推断。**布尔类型**
> (Bool)
Swift 有一个基本的布尔(Boolean)类型,叫做Bool。布尔值指逻辑上的值,因为它们只能是真或者假。Swift 有两个布尔常量,true和false。
**字符和字符串类型**
> (Character/String)
只包含一个字符的时候,我们也可以把它作为字符类型,Character 只是 String 的一种特殊情况,一般来说,我们都使用 String 就好了[demo19.swift](examples/demo19.swift):
```swift
var ch: Character = "a"
var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化 String 实例
// 两个字符串均为空并等价。
// 通过检查其Boolean类型的isEmpty属性来判断该字符串是否为空
if emptyString.isEmpty {
print("什么都没有")
}
// 打印输出:"什么都没有"
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// 打印输出:"unusualMenagerie has 40 characters"// +相加在一起(或称“串联”)
var str1 = "hello";
var str2 = " there";
var str = str1 + str2;
print(str);
// welcome 现在等于 "hello there"let normal = "Could you help me, please?"
// 转化大写
let shouty = normal.uppercaseString
// shouty 值为 "COULD YOU HELP ME, PLEASE?"
// 转化小写
let whispered = normal.lowercaseString
// whispered 值为 "could you help me, please?"
```- 一个字符串中并不一定占用相同的内存空间
字符串常量可以包括下面这些特殊字符:
- 空字符`\0`,反斜杠`\`,制表符`\t`,换行符`\n`,回车符`\r`,双引号`\"`和单引号`\'`
- 单字节Unicode字符,`\xnn`,其中nn是两个十六进制数
- 双字节Unicode字符,`\unnnn`,其中nnnn是四个十六进制数
- 四字节Unicode字符,`\Unnnnnnnn`,其中nnnnnnnn是八个十六进制数**数组和字典**
数组和字典是两种非常长常见的数据类型,在刚才介绍的类型中,一个量通常只能包含一个值。而数组这种类型,就可以容纳相同类型的的多个值;而字典这种类型,可以容纳多个对应关系(一个值唯一对应另一个值)
```swift
var stringArray: [String] = ["This", "is", "github"]// 并通过下面的方式可以访问数组和字典中的值
print(stringArray[0]) // 访问第0个值, 数组的元素是从0开始记的
```### 数值范围
下表显示了不同变量类型内存的存储空间,及变量类型的最大最小值:
| 类型 | 大小(字节) | 区间值 |
| ---- | ---- | ---- |
| Int8 | 1 字节 | -127 到 127 |
| UInt8 | 1 字节 | 0 到 255 |
| Int32 | 4 字节 | -2147483648 到 2147483647 |
| UInt32 | 4 字节 | 0 到 4294967295 |
| Int64 | 8 字节 | -9223372036854775808 到 9223372036854775807 |
| UInt64 | 8 字节 | 0 到 18446744073709551615 |
| Float | 4 字节 | 1.2E-38 到 3.4E+38 (~6 digits) |
| Double | 8 字节 | 2.3E-308 到 1.7E+308 (~15 digits) |### 类型别名
类型别名对当前的类型定义了另一个名字,类型别名通过使用 typealias 关键字来定义。语法格式如下:
> typealias 类型名字 = type
```swift
// 例如以下定义了 Int 的类型别名为 Feet:
typealias Feet = Int// 由于前面已经定义了类型别名,那么这里使用Feet也相当于使用Int
// 所以AudioSample.min = Int.min,也就是0.
var maxAmplitudeFound = Feet.min;
// 几面输出 maxAmplitudeFound: Int = -9223372036854775808// 现在,我们可以通过别名来定义变量:
typealias:Feet = Intvar
distance: Feet = 100
print(distance)
// 我们使用 playground 执行以上程序,输出结果为:
// 100·
```### 类型安全
Swift 是一个类型安全(type safe)的语言。由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。[demo16.swift](examples/demo16.swift)
```swift
import Cocoa
var A = 42
A = "This is hello"
print(A)
``````bash
$ swift examples/demo16.swift
examples/demo16.swift:3:5: error: cannot assign value of type 'String' to type 'Int'
A = "This is hello"
^~~~~~~~~~~~~~~
```### 类型推断
如果你没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。[demo17.swift](examples/demo17.swift)
```swift
// a 会被推测为 Int 类型
let a = 42// pi 会被推测为 Double 类型
let pi = 3.14159// anotherPi 会被推测为 Double 类型
// 原始值3没有显式声明类型,而表达式中出现了一个浮点字面量,
// 所以表达式会被推断为Double类型。
let anotherPi = 3 + 0.14159print(anotherPi)
//上面输出 3.14159
```### 元组和集合
元组不是一种类型,但是却是一种可以表示数据的结构。数组保存多个相同类型的值,而元组则可以保存多个不同类型的值,它的用法如下[demo15.swift](examples/demo15.swift):
```swift
let awesome = ("Swift", 3, "awesome.")
let (a, b, c) = awesome
print(a) // 输出 Swift
print(b) // 输出 3
print(c) // 输出 awesome.// 和数组、字典不同的是,你不能通过[] 的方式来访问元组中的内容,但你可以像这样
print(awesome.0)
```集合的声明和数组非常类似,都是通过 [] 进行,不同的地方在于集合只能容纳不同的值,而数组可以容纳相同的值:
```swift
let sets: Set = [1, 2, 3, 4]
let arrays: Array = [1, 1, 1, 1]
```上面定义了 sets 是一个 Set 集合类型,容纳的是 Int 类型的值,数组同理
默认情况下,如果你不做显式声明,Swift 会默认将其推断为数组类型
关于集合、数组、字典之间的关系,下面这张图很好的展示了这一切:[画图工具](http://asciiflow.com/)```bash
Array Set Dictionary
┏--------------┓ ┏---------------┓ ┏-------------------------┓
┆ Index Value ¦ ¦ Value ¦ ¦ Keys Values ¦
¦ ┌---┬------┐ ¦ ¦ ¦ ¦ ┌----┐ ┌-------┐ ¦
¦ ¦0 ¦Six ¦ ¦ ¦ ┌----┐ ¦ ¦ ¦YYZ ├-------▷¦Toronto¦ ¦
¦ ├---┼------┤ ¦ ¦ ¦Rock¦ ┌----┐ ¦ ¦ ├----┤ └-------┘ ¦
¦ ¦1 ¦Milk ¦ ¦ ¦ └----┘ ¦Jazz¦ ¦ ¦ ¦DUB ├---┐ ¦
¦ ├---┼------┤ ¦ ¦ └----┘ ¦ ¦ ├----┤ ¦ ┌-------┐ ¦
¦ ¦2 ¦Flour ¦ ¦ ¦ ┌-----┐ ¦ ¦ ¦LHR ├---┼---▷¦London ¦ ¦
¦ ├---┼------┤ ¦ ¦ ¦Class¦ ┌---┐ ¦ ¦ └----┘ ¦ └-------┘ ¦
¦ ¦3 ¦Powder¦ ¦ ¦ └-----┘ ¦Cat¦ ¦ ¦ ¦ ¦
¦ ├---┼------┤ ¦ ¦ └---┘ ¦ ¦ ¦ ┌-------┐ ¦
¦ ¦4 ¦Hello ¦ ¦ ¦ ¦ ¦ └---▷¦Dubin ¦ ¦
¦ └---┴------┘ ¦ ¦ ¦ ¦ └-------┘ ¦
┗--------------┛ ┗---------------┛ ┗-------------------------┛
```## 可选和隐式可选类型
- 类型后面用问号 `?` 表示可选类型;
- 类型后面用感叹号 `!` 表示隐式可选类型;### 可选类型
当基础类型(整形、浮点、布尔等)没有值时,是不能使用的。Swift 为了表达这种状态,对类型提供了可选的概念。在某个类型后面添加 ? 可以表示一个可选类型,这个可选类型有两种状态:1. 有值;2. 没值
```swift
var optionalInteger: Int?
optionalInteger = 404if optionalInteger != nil { // 确定可选类型包含值后可以在变量名后加!强制解析
print(optionalInteger!) // 404
}var errorCode: Int? = 404 // 在类型后面添加一个?
print(errorCode) // Optional(404) // 会打印警告
errorCode = nil // 对非可选类型赋值为nil会报错
print(errorCode) // nil // 会打印警告// 确定可选类型包含值后可以在变量名后加!强制解析
if errorCode != nil {
print(errorCode!)// 404
}
```## 问题解决
- [swift NameError: name 'run_one_line' is not defined](https://github.com/Homebrew/homebrew-core/issues/2712)
## 工具
- [Carthage](https://github.com/Carthage/Carthage) 一个简单的,分散的Cocoa依赖管理器
- [CocoaPods](https://github.com/CocoaPods/CocoaPods) Swift和Objective-C Cocoa项目的依赖管理器。## Web框架
- [apple/swift-nio](https://github.com/apple/swift-nio)
- [Vapor](https://github.com/vapor/vapor)
- [Perfect](https://github.com/PerfectlySoft/Perfect)
- [Kitura](https://github.com/IBM-Swift/Kitura)
- [Zewo](https://github.com/Zewo/Zewo)
- [Smoke](https://github.com/amzn/smoke-framework)## 参考教程
- [The Swift Programming Language 中文版](http://special.csdncms.csdn.net/the-swift-programming-language-in-chinese/Introduction.shtml)
- [官方文档The Swift Programming Language](https://swift.org/documentation/#the-swift-programming-language)
- [官方文档的中文版The Swift Programming Language中文版](https://github.com/numbbbbb/the-swift-programming-language-in-chinese)
- [Swift3.0语法速查手册](https://darielchen.github.io/SwiftManual/)
- [戴铭的 Swift 小册子](https://ming1016.github.io/2021/11/23/daiming-swift-pamphlet/)
- [探索函数式编程和 Swift 的视频系列](https://github.com/pointfreeco/episode-code-samples)
- [SwiftUI 相关文章](https://serialcoder.dev/category/text-tutorials/swiftui/)
- [深入浅出 Swift 3](https://www.shiyanlou.com/courses/611)
- [Swift教程](http://c.biancheng.net/cpp/swift/jiaocheng/)
- [慕课网Swift教程](http://www.imooc.com/search/course?words=swift)
- [Swift 必备 tips](http://swifter.tips)
- [Swift 学习指引](http://www.swiftguide.cn)
- [swiftcafe](http://swiftcafe.io)
- [SwiftGG](http://swift.gg)
- [swiftweekly](http://swiftweekly.cn)
- [dianqk](http://blog.dianqk.org)## Contributors
As always, thanks to our amazing contributors!
Made with [action-contributors](https://github.com/jaywcjlove/github-action-contributors).
## License
Licensed under the MIT License.