这篇笔记是初次接触Swift写的笔记,十分适合啥都不会的/稍微看了些官方文档的人,这篇笔记做得十分浅显,其实是没啥汇编内容的,因为自己看编译部分也是半懂不懂的看完的。总之,如果这篇笔记能给你带来帮助,这将是莫大荣幸。笔记基于小码哥Swift5.1课程。
Swift5.0 1(应用二进制接口)已经稳定。
编译流程
编译器前端:词法分析…;后端:生成对应平台的二进制代码
对汇编代码进行分析可以掌握编程语言的本质
Hello World
Print("Hello World!")
var a =0
let cons = 10
print("\(a)") //输出变量
不用编写main函数,Swift将全局范围内的首句可执行代码作为程序入口。
用var 定义变量;用let 定义常量。
一行内只有一句语句可不用分号。
常量
let con:Int
con =10 ✅
常量可以不在编译时确定,但需要保证在使用前赋值:
var num =10 num =20 let age = num ✅
标识符
标识符可以使用几乎任何字符。但不能:
- 包含空白字符,制表符,箭头等特殊字符
数据类型
int是结构体,但性能并不会差。
也因此,我们可以UInt8.min/UInt16.min
字面量
定义字符时要注明Character,不然会变成字符串
类型转换
元组
let error(statusCode:404, description:"Not Found")
let (justTheCode, _) = error
print("The Status Code is : \(error.statusCode)")
流程控制
if
if后面的条件可以省略小括号。
条件后面的括号不可以省略。
if后面的条件只能是Bool类型(不可以用1,0表示)
while
repeat-while相当于C语言的do-while
var num = -1 repeat{ print("num is \(num)") }while num>0
- 从Swift3开始,去除了++和–运算符
for
for使用区间运算符。
区间运算符:
- 闭区间运算符:0…3 : 0,1,2,3
- 半开运算符:a…<10
- 单侧区间:2…,…2,…<2(尽可能延展)
for i in 0...3 { //..... }✅ let range = 0...3 for i in range{ //..... }✅ for _ in 0...3{ //..... }//当不使用i时,可以使用_替代 for var i in 0...3{ i += 1; print(i) }//i默认是常量,可以声明为变量 let name = ['A','B','C'] for name in names[0...2]{ //..... }//用在数组上
区间运算符
- 检查某个字符在不在一个区间:
带有间隔的区间值:
let hourInterval = 2 for tricjMark in stride(form:4, through:11, by:hourInterval){ //... }
switch
Switch 默认break,并不会贯穿到后面的条件。
使用fallthrough贯穿case
switch必须要能处理所有情况,不然会报错。
- 如果只想要处理其中几个情况:
var number = 1 switch number { case 1: print("1") case 2: print("2") default: break //✅ }
如果能保证已处理所有情况,也可不必使用default:
enum Answer {case right, wrong}let answer = Answer.rightswitch answer {case Answer.right: print("RIGHT")case Answer.wrong: print("WRONG")}
区间匹配,元祖匹配:
//区间匹配
let count = 62
switch count {
case 0:
print("none")
case 1..<50:
print("a few")
default:
print("many")
}
//元祖匹配
let point = (1,1)
switch point {
case (0,0):
print("the origin")
case (_,0):
print("on the x-axis")
case (0,_):
print("on the y-axis")
case(-2...2,-2...2):
print("inside the box")
default:
print("outside of the box")
}
值绑定
let point = (2,0)
switch point {
case (let x,0):
print("on the x-axis with an x value of \(x)")
case (0,let y):
print("on the y-axis with a y value of \(y)")
case let(x,y):
print("somewhere else at (\(x),\(y))")
}
where
let point = (1,1)
switch point {
case let(x,y) where x==y:
print("on the line x==y")
case let(x,y):
print("at (\(x),\(y))")
}
where还可以用在for
var number = [10,20,-30,40] var sum = 0 for num in number where num > 0 { sum += num }
函数
func sum(_ v1: Int, _ v2:Int) -> Int {
return v1 + v2
}
sum(10,10)
形参默认是let,也只能是let
无返回值直接不写->
实现多返回值——使用元组
func caculate(v1:Int,v2:Int) -> (sum:Int,difference:Int,average:Int) {
let sum = v1 + v2
return (sum,v1-v2,sum>>1)
}
let result = caculate(v1:20,v2:10)
print(result.sum)
print(result.difference)
print(result.average)
文档注释
参数标签
func goToWork(at time:String) {
print("this is \(time)")
}
goToWork(at:"08:00")
默认参数值
func check(name:String = "nobody", age:Int, job:String = "none") {
print("name:\(name),age=\(age),job=\(job)")
}
可变参数
public func print(_ items:Any..., separator:String = " ", terminator:String = "\n")
输入输出参数
用inout
定义一个输入输出参数可以在函数内部修改外部实参的值
实际上是地址传递
var number = 10
func add(_ num: inout Int){
num = 20
}
add(&number)
函数重载
规则:
- 函数名相同
- 参数个数不同||参数类型不同||参数标签 不同
返回值类型与函数重载无关
内联函数
如果开启了编译器优化,编译器会自动将某些函数变成内联函数
可以使用@inline控制内联
函数类型作为函数参数
func sum(v1:Int, v2:Int) -> Int {
v1 + v2
}
func printResult(_ mathFunc:(Int, Int)->Int, _ a:Int, _ b:Int) {
print("Result:\(mathFunc(a,b))")
}
函数类型作为函数返回值
func next(_ input:int) -> int {
input + 1
}
func previous(_ input:Int) -> Int{
input - 1
}
func forward(_ forward:Bool) -> (Int)->Int{
forward?next:previous
}//forward被叫做高阶函数
forward(true)(3) //4
forward(false)(3)//2
typealias——给类型起一个别名
typealias byte = Int8
typealias Date = (year:Int, month:Int, day:Int)
func test(_ date:Date){
pint(date.0)
}
test((2011,9,10))
嵌套函数
将函数定义在函数内部
内部函数只能在外部函数内部调用和使用
枚举
enum Direction {
case north
case south
case east
case west
}
var dir = Direction.west
dir = .north
print(dir) //north
关联值
将枚举成员值与其他类型的关联存储在一起
enum Score {
case points(Int)
case grade(Character)
}
var score = Score.points(96)
score = .grade("A")
switch score {
case let .points(i):
print(i,"points")
case let .grade(i):
print("grade",i)
}
原始值
枚举成员可以使用相同类型的默认值预先关联,这个默认值叫做原始值
enum pokerSuit : Character {
case spade = "♠︎"
case heart = "♥︎"
//.....
}
print(pokerSuit.spade.rawValue)
隐式原始值
如果枚举类型为Int/String,swift会自动分配原始值。(Int:0…;String:同名)
递归枚举
indirect enum ArithExpr {
case number(Int)
case sum(ArithExpr,ArithExpr)
}
可选项
可选项,也叫做可选类型,它允许将值设为nil
。可选项像一个盒子,将数据放了进去。
其他类型不允许设置为空值(nil)
在类型名称后加?
来定义一个可选项:
var age: Int?//可选项初始值默认为nil
age = 10
age = nil
强制解包
如果可选项不为nil
,那么可选项(盒子)里装的是被包装类型的数据。如果要从可选项中取出被包装的数据,使用!
进行强制解包。
var age:Int? = 10
let ageInt:Int = age!
ageInt += 10 //20
对值为nil的可选项强制解包,会产生运行错误。
可选项绑定
可选项绑定可以判断可选项是否包含值,如果包含值就自动解包,把值赋予一个常量或者变量,并返回true或false
if let number = Int("123") {
print(nnumber)
}else{
print("转换失败")
}
//注意,number的作用域为if语句内
在while中使用可选绑定
var strs = ["10","20","abc","-20","30"]
var index = 0
var sum = 0
while let num = Int(strs[index]), num > 0 {
sum += num
index += 1
}
print(sum)//30
空合并运算符??
a ??
b : 如果a不为nil,则返回a,否则返回b
如果b不是可选项,则返回的a会自动解包
隐式解包
var num:Int! = 10
可选项打印时
多重可选项
var num1:Int? = 10
var num2:Int?? = num1
var num3:Int?? =10
print(num3 == num2)//true
guard
当guard语句的条件为false时,就会执行大括号里面的句子。
guard语句内一定要有退出语句,不然会报错。
guard语句适合用来做提前退出。
guard condition else {
//...
return //return,break,continue,throw error
}
当使用guard语句进行可选项绑定时,绑定的常量或者变量也能在外层作用域中使用:
func login(_ info:[String:String]) { guard let username = info["username"] else { print("username missing") return } guard let password = info["password"] else { print("password missing") return } print("USER:\(username);PASS:\(password)") }
应用程序与系统之间底的底层接口。涉及:目标文件格式,数据类型个大小、布局、对齐,函数调用约定等。 ↩︎