经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
Swift 进阶(一)基础语法
来源:cnblogs  作者:FunkyRay  时间:2021/3/8 14:11:10  对本文有异议

Swift简介

在学习Swift之前,我们先来了解下什么是Swift

Swift是Apple在2014年6月WWDC发布的全新编程语言,中文名和LOGO是”雨燕“

Swift之父是Chris Lattner,也是Clang编译器的作者,LLVM项目的主要发起人

Swift版本

Swift历时七年,从Swift 1.*更新到Swift 5.*,经历了多次重大改变,ABI终于稳定

API(Application Programming Interface):应用程序编程接口

  • 源代码和库之间的接口

ABI(Application Binary Interface):应用程序二进制接口

  • 应用程序和操作系统之间的底层接口
  • 涉及的内容有:目标文件格式、数据类型的大小/布局/对齐,函数调用约定等

Swift是完全开源的,下载地址:https://github.com/apple/swift

Swift编译原理

LLVM编译器

LLVM编译器一般分为前端和后端

  • 前端:主要进行词法分析,生成语法树
  • 后端:生成对应平台的二进制代码

编译流程

我们知道OC的前端是通过Clang进行编译的,Swift的前端是通过swiftc来编译的

不同语言的前端可能不同,但最终都会通过编译器的后端生成对应平台的二进制代码

-w727

整个编译流程如下图所示

-w525

  • Swift Code:我们编写的Swift代码
  • Swift AST:Swift语法树
  • Raw Swift IL:Swift特有的中间代码
  • Canonical Swift IL:更简洁的Swift特有的中间代码
  • LLVM IR:LLVM的中间代码
  • Assembly:汇编代码
  • Executable:二进制代码

关于Swift编译流程的详细讲解可以参考以下网址:https://swift.org/swift-compiler/#compiler-architecture

swiftc

我们打开终端,输入swiftc -help,会打印出相关指令,这也说明了swiftc已经存在于Xcode中

-w890

我们可以在应用程序中找到Xcode,然后右键显示包内容,通过该路径找到swiftc

路径:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

-w1175
-w788

swiftc的基本操作演练

下面我们可以通过一些swiftc的一些基本操作来了解

1.我们先新建一个Swift的命令行项目

-w1399
-w1076

2.然后打开终端,cdmain.swift路径

-w890

3.然后我们输入swiftc -dump-ast main.swift,来查看下生成的语法树

-w890

4.我们还可以输入swiftc -emit-sil main.swift生成最简洁的SIL代码

-w890

5.我们还可以输入swiftc -emit-ir main.swift生成LLVM IR中间代码

-w890

6.我们还可以输入swiftc -emit-assembly main.swift生成汇编代码

-w890

Swift基础语法

Swift中打印输入:print("Hello World")

Swift中一句代码是可以省略分号的,但是如果多句代码写在一行,需要用分号隔开

常量和变量

常量:

1.用let定义常量,常量只能赋值一次

不用特意指明类型,编译器会自动进行推断

  1. let a: Int = 10
  2. let b = 20

2.它的值不要求在编译过程中确定,但使用之前必须赋值一次

这样写确定了a的类型,之后再去赋值,也不会报错

  1. let a: Int
  2. a = 10

用函数给常量赋值也可以,函数是在运行时才会确定值的,所以只要保证使用之前赋值了就行

  1. func getNumber() -> Int {
  2. return 10
  3. }
  4. let a: Int
  5. a = getNumber()

如果没有给a确定类型,也没有一开始定义的时候赋值,就会像下面这样报错

-w643

变量:

1.用var定义变量

  1. var b = 20
  2. b = 30

2.常量、变量在初始化之前,都不能使用

-w644

注释

1.Swift中有单行注释和多行注释

注释之间嵌套也没有问题

  1. // 单行注释
  2. /*
  3. 多行注释
  4. /*
  5. 多行注释
  6. */
  7. /*
  8. // 注释嵌套
  9. */

2.Playground里的注释支持Markup语法(同Markdown)

Markup语法只在Playground里有效,在项目中无效

  1. //: # 一级标题
  2. /*:
  3. ## 基础语法
  4. */

可以通过Editor -> Show Raw Markup来预览

-w299

预览的效果如下

-w369

标识符

1.标识符(比如常量名、变量名、函数名)几乎可以使用任何字符

  1. let ?? = 5
  2. var ?? = 10
  3. func ??() {
  4. }

标识符不能以数字开头,不能包含空白字符、制表符、箭头等特殊字符

-w649

常见数据类型

常见类型

  • 值类型
    • 枚举(enum): Optional
    • 结构体(struct): Bool、Double、Float、Int、Character、String、Array、Dictionary、Set
  • 引用类型
    • 类(class)

可以通过command+control进入到该类型的API中查看

例如Int类型

-w757

整数类型

整数类型:Int8、Int16、Int32、Int64、UInt8、UInt16、UInt32、UInt64

在32bit平台,Int等于Int32;在64bit平台,Int等于Int64

整数的最值:UInt8.max,Int16.min

一般情况下,都是直接使用Int即可

  1. let a: Int8 = 5

浮点类型

Float:32位,精度只有6位

Double:64位,精度至少15位

浮点型不指明类型默认就是Double

  1. let a: Float = 2.0
  2. let b = 3.0

字面量

字面量就是指这个量本身,就是一个固定值的表示法

下面这些都是字面量

Bool布尔

一般用Bool类型来表示是否的判断,是为true,否为false

  1. let bool = true
字符串、字符

字符串的写法

  1. let string = "hello"

字符类型要写上Character,否则会被认为是字符串

字符可存储ASCII字符、Unicode字符

  1. let character: Character = "a"
整数

不同进制的表示法

  • 二进制以0b开头
  • 八进制以0o开头
  • 十六进制以0x开头
  1. let intDecimal = 17 // 十进制
  2. let intBinary = 0b10001 // 二进制
  3. let intOctal = 0o21 // 八进制
  4. let intHexadecimal = 0x11 // 十六进制
浮点数
  1. let doubleDecimal = 125.0 // 十进制
  2. let doubleDecimal2 = 1.25e2 // 也是125.0的另一种写法,表示1.25乘以10的二次方
  3. let doubleDecimal3 = 0.0125
  4. let doubleDecimal4 = 1.25e-2 // 也是0.0125的另一种写法,表示1.25乘以10的负二次方
  5. let doubleHexadecimal1 = 0xFp2 // 十六进制,意味着15*2^2(15乘以2的二次方),相当于十进制的60
  6. let doubleHexadecimal2 = 0xFp-2 //十六进制,意味着15*2^-2(15乘以2的负二次方),相当于十进制的3.75

整数和浮点数可以添加额外的零或者下划线来增强可读性

  1. let num = 10_0000
  2. let price = 1_000.000_000_1
  3. let decimal = 000123.456
数组
  1. let array = [1, 2, 3, 4]
字典
  1. let dictionary = ["age" : 18,
  2. "height" : 1.75]

类型转换

整数转换

  1. let int1: UInt16 = 2_000
  2. let int2: UInt8 = 1
  3. let int3 = int1 + UInt16(int2)

整数、浮点数转换

  1. let int = 3
  2. let double = 0.1415926
  3. let pi = Double(int) + double
  4. let intPi = Int(pi)

字面量可以直接相加,因为数字字面量本身没有明确的类型

  1. let result = 3 + 0.14159

元组(tuple)

元组是可以多种数据类型组合在一起

  1. let http404Error = (404, "Not Found")
  2. print("The status code is \(http404Error.0)")
  3. // 可以分别把元组里的两个值分别进行赋值
  4. let (statusCode, statusMsg) = http404Error
  5. print("The status code is \(statusCode)")
  6. // 可以只给元组里的某一个值进行赋值
  7. let (justTheStatusCode, _) = http404Error
  8. // 可以在定义的时候给元组里面的值起名
  9. let http200Status = (statusCode: 200, description: "ok")
  10. print("The status code is \(http200Status.statusCode)")

流程控制

if-else

Swift里的if else后面的条件是可以省略小括号的,但大括号不可以省略

  1. let age = 10
  2. if age >= 22 {
  3. print("Get married")
  4. } else if age >= 18 {
  5. print("Being a adult")
  6. } else if age >= 7 {
  7. print("Go to school")
  8. } else {
  9. print("Just a child")
  10. }

if else后面的条件只能是Bool类型

-w718

while

  1. var num = 5
  2. while num > 0 {
  3. print("num is \(num)")
  4. // 打印了五次
  5. }

repeat-while相当于C语言中的do-while

先执行一次,再判断条件循环

  1. var num = -1
  2. repeat {
  3. print("num is \(num)")
  4. // 打印了一次
  5. } while num > 0

这里不用num--是因为Swift3开始,已经去掉了自增(++)、自减(--)运算符

for

1.闭区间运算符:a...b,相当于a <= 取值 <= b

  1. // 第一种写法
  2. let names = ["Anna", "Alex", "Brian", "Jack"]
  3. for i in 0...3 {
  4. print(names[i])
  5. }
  6. // 第二种写法
  7. let range = 0...3
  8. for i in range {
  9. }
  10. // 第三种写法
  11. let a = 1
  12. let b = 3
  13. for i in a...b {
  14. }

循环里的i默认是let,如需要更改加上var

  1. for var i in 0...3 {
  2. }

不需要值的时候用_来表示

  1. for _ in 0...3 {
  2. }

2.半开区间运算符:a..<b,相当于a <= 取值 < b

  1. for i in 0..<3 {
  2. }

3.单侧区间:让一个区间朝一个方向尽可能的远

  1. for i in ...3 {
  2. }
  3. for _ in 3... {
  4. }

4.区间运算符还可以用在数组上

  1. let names = ["Anna", "Alex", "Brian", "Jack"]
  2. for name in names[0...3] {
  3. print(name)
  4. }
  5. for name in names[2...] {
  6. print(name)
  7. }
  8. for name in names[...2] {
  9. print(name)
  10. }
  11. for name in names[..<2] {
  12. print(name)
  13. }
  14. let range = ...5
  15. range.contains(4)

5.区间的几种类型

  1. 闭区间 ClosedRange<Int>
  2. 1...3
  3. 半开区间 Range<Int>
  4. 1..<3
  5. 单侧区间 PartialRangeThrough<Int>
  6. ...3

6.字符、字符串也能使用区间运算符,但默认不能用在for-in

  1. let stringRange1 = "cc"..."ff"
  2. stringRange1.contains("cd")
  3. let stringRange2 = "a"..."f"
  4. stringRange2.contains("c")
  5. let characterRange:ClosedRange<Character> = "\0"..."~"
  6. characterRange.contains("G")

7.带间隔的区间值

  1. let hours = 10
  2. let hourInterval = 2
  3. // tickmark的取值,从4开始,累加2,不超过10
  4. for tickmark in stride(from: 4, through: hours, by: hourInterval) {
  5. print(tickmark)
  6. // 4,6,8,10
  7. }

switch

使用同C语言的switch,不同的是case、default后面不写大括号{}

  1. var number = 1
  2. switch number {
  3. case 1:
  4. print("number is 1")
  5. break
  6. case 2:
  7. print("number is 2")
  8. break
  9. default:
  10. print("number is other")
  11. break
  12. }

默认不写case,并不会贯穿到后面的条件

  1. var number = 1
  2. switch number {
  3. case 1:
  4. print("number is 1")
  5. case 2:
  6. print("number is 2")
  7. default:
  8. print("number is other")
  9. }

使用fallthrough可以实现贯穿效果

  1. var number = 1
  2. switch number {
  3. case 1:
  4. print("number is 1")
  5. fallthrough
  6. case 2:
  7. print("number is 2")
  8. default:
  9. print("number is other")
  10. }
  11. // 会同时打印number is 1,number is 2

switch必须要保证能处理所有情况

注意:像判断number的值,要考虑到所有整数的条件,如果不要判断全部情况,加上default就可以了

-w722

case、default后面至少要有一条语句

如果不想做任何事,加个break即可

  1. var number = 1
  2. switch number {
  3. case 1:
  4. print("number is 1")
  5. case 2:
  6. break
  7. default:
  8. break
  9. }

如果能保证已处理所有情况,也可以不必使用default

  1. enum Answer { case right, wrong }
  2. let answer = Answer.right
  3. switch answer {
  4. case .right:
  5. print("right")
  6. case .wrong:
  7. print("wrong")
  8. }

switch也支持CharacterString类型

  1. let string = "Jack"
  2. switch string {
  3. case "Jack":
  4. fallthrough
  5. case "Rose":
  6. print(string)
  7. default:
  8. break
  9. }

switch可以同时判断多个条件

  1. let string = "Jack"
  2. switch string {
  3. case "Jack", "Rose":
  4. print(string)
  5. default:
  6. break
  7. }
  8. let character: Character = "a"
  9. switch character {
  10. case "a", "A":
  11. print(character)
  12. default:
  13. break
  14. }

switch也支持区间匹配和元组匹配

  1. let count = 62
  2. switch count {
  3. case 0:
  4. print("none")
  5. case 1..<5:
  6. print("a few")
  7. case 5..<12:
  8. print("several")
  9. case 12..<100:
  10. print("dozens of")
  11. default:
  12. print("many")
  13. }

可以使用下划线忽略某个值

  1. let point = (1, 1)
  2. switch point: {
  3. case (2, 2):
  4. print("1")
  5. case (_, 0):
  6. print("2")
  7. case (-2...2, 0...):
  8. print("3")
  9. }

值绑定,必要时let也可以改成var

  1. let point = (2, 0)
  2. switch point: {
  3. case (let x, 0):
  4. print(x)
  5. case (0, let y):
  6. print("2")
  7. case let (x, y):
  8. print("3")
  9. }

where

一般where用来结合条件语句进行过滤

  1. let point = (1, -1)
  2. switch point {
  3. case let (x, y) where x == y:
  4. print("on the line x == y")
  5. case let (x, y) where x == -y:
  6. print("on the line x == -y")
  7. case let (x, y):
  8. print("\(x), \(y) is just some arbitrary point")
  9. }
  10. for i in 0...5 where i == 3 {
  11. print(i)
  12. }

标签语句

outer来标识循环跳出的条件

  1. outer: for i in 1...4 {
  2. for k in 1...4 {
  3. if k == 3 {
  4. continue outer
  5. }
  6. if i == 3 {
  7. break outer
  8. }
  9. }
  10. }

原文链接:http://www.cnblogs.com/funkyRay/p/swift-jin-jie-yi-ji-chu-yu-fa.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号