0.Swift语言背景的介绍
- 历史6年(2014年6月发布),Swift从1.x发展到5.x,经历了多次重大改变,ABI终于稳定
- ABI(Application Binary Interface):应用二进制接口,应用程序和操作系统之间的底层接口,涉及到:
- 1.目标的文件格式
- 2.数据类型的大小,布局,对齐
- 3.函数的调用约定等等
- ABI稳定以后,语法不会有太大变动
- Swift是用C++编写的
1. playground 使用
关于playground的创建和使用这里不赘述了,百谷一堆(😁百度和谷歌一查一堆一堆的),它的优点就是可以试试预览一些结果,比如输入 a+b,他就能反映出a+b的结果,也可以预览一些视图的比如背景色之类的
1.1 常用快捷键
- cmd + shift + enter 运行整个prayground
- shift + enter 运行到某行及之前的代码
1.2 视图预览
- 如果需要预览视图,需要
import PlaygroundSupport
,然后将要显示的view赋值给以下代码PlaygroundPage.current.liveView = view
,- 如果不显示预览视图,可以试试
cmd+option+enter
- 添加图片资源,cmd+1,展开左边的文件夹目录,将资源拖拽到
Resource
中,则可以引用图片资源 Source
文件夹是存放代码文件的- 同样也可以创建控制器,不赘述了,详细看demo
1.3 多page介绍
- Xcode菜单栏
File -> New -> Playground Page
或者 快捷键option+cmd+n
- 新建的page可以自由修改名字,可以拖动位置,每个page包含单独的
Source
和Resource
,在每个page每部的文件夹内的资源是只有当前page可以使用,项目的Source
和Resource
是所有的page都共享的
1.4 Markdown语法支持
playground 可以与注释配合生成对Markdown语法的渲染,这里不过多赘述Markdown的语法,百谷一堆。
- 单行行注释的Marksown:
//:
双反斜杠加冒号,斜杠和冒号之间不能有空格,后面跟单行的Markdow语句
//:# 这是Markdown的一级标题
- 多行注释注释的Marksown:
/*: 这里写Markdown语句 */
/*:
# 这是Markdown的一级标题
## 这是Markdown的二级标题
### 这是Markdown的三级标题
*/
-
同一个playground下的多个page的跳转
@next
和@previous
//: [下一页](@next)
自动跳转到当前page的下一个page,并显示为下一页
,如果当前page没有下一页的话,则点击无效//: [上一页](@previous)
自动跳转到当前page的上一个page,并显示为上一页
,如果当前page没有上一页的话,则点击无效
-
Markdown语法编写完毕之后通过Xcode -> Editor -> Show Rendered Markup
2.简单入门
这一节中我们只是泛泛的简单的演示一些操作,对于有编程基础一看就能懂的东西,不做过多赘述
2.1 我们先创建一个命令行项目,大致观察一下项目结构
// 导包
import Foundation
// 打印
print("Hello, World!")
- 项目很简单:
- 仅包含一个main文件,
- main文件中并没有我们熟悉的main函数,
- 实现
Hello, World!
只需要一行代码,更简单甚至可以去掉导包 - Swift项目的文件的后缀名为
.swift
,和OC项目不同的是,不再区分声明.h和实现.m - 一句代码尾部可以省略分号,多句代码如果在同一一行,必须用分号隔开
2.2 简单了解print
- 基本打印,在
print
函数里直接书输入变量名字 - 字符拼接,只需要在字符串中使用
\(变量名)
进行包裹即可 TUDO - 基本打印
2.3 简单了解变量和常量
- 常量
- 用
let
声明不可以重复赋值,重复赋值会报错 - 常量不要求在编译期就明确赋值,但是只能赋值1次
- 未标明类型的常量,或者不能通过自动推断出变量类型的,必须在声明时赋值
- 用
- 变量用
var
声明,可以重复赋值, - 变量或者常量不需要声明类型,编译器通过自动推断出类型
3.Swift数据类型
与OC不同的是,Swift的数据类型大致分类两种,或者三种,按照两种划分
- 值类型 -
enum + struct
- 引用类型 -
class
按照三种划分,可以将enum 和 struct 各自作为一类。enum 这个不足赘述了,后续会详细展开,struct类型的范围是与OC最大的不同,其中Bool Int Float Double Character 以及String Array Dictionary Set都是用struct实现的
3.1 简单介绍数据类型
整形
- 整形类型: Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64
- 在32位系统,Int等价于Int32,64位系统等价于Int64
浮点型:
-
Float 32位,精度6位,
-
Double 64位,精度至少15位
-
浮点型定义变量时默认为Double,如果是用Float类型时,要显式标注
// 浮点型 let double = 15.0 // Double 类型 let float:Float = 10.0 //Float 类型
布尔类型
- 在OC中 0,1,YES,NO,true,flase都可以作为布尔类型的赋值,但是在Swift中只能是true false,不接受其他值
字符和字符串
-
字符和字符串都是使用双引号,再不加类型标注的时候默认是字符串,如果是定义字符需要显式的标注
// 字符 和 字符串 let string = "字符串" let character:Character = "😁"
3.2 类型转换
-
Swift在进行数值计算时,不会进行类型自动转换,比如我们以前在OC中一个浮点型 加上 一个整形数据,然后结果会看做浮点型,相当于是自动转换为优先级高的类型,但是在Swift中不允许这样进行计算,要求进行计算的结果变量类型一定是一致的,否则就会报错
-
Swift类型强转,格式为
类型(要转换的值)
,下面的例子是将Float转换为Double,通过这个例子也能看出,同是浮点类型的数据,也不能直接计算// 浮点型 let double = 15.0 // Double 类型 let float:Float = 10.0 //Float 类型 let value = double + Double(float)
-
这里有个例外就是如果字面量直接向加减是不会报错的,因为没有明确的表明类型,最后系统会根据数值进行推断的
let value = 1 + 0.5
4.元组
概念不多介绍了,百谷一堆。介绍几种赋值和定义的方式
// 元组
// 1.基本定义
let tuple = (0,"我是字符串",true)
// 2.根据每个元素名字定义
let (intValue,stringValue,boolValue) = (0,"我是字符串",true)
intValue
stringValue
boolValue
// 3.第二种也可以省略其中不需要取值元素
let (_,stringValue1,boolValue1) = (1,"我是字符串2",true)
// 4.也可以在实现的时候声明元素名字
let tuple2 = (int:2, string: "我是字符串3", bool:true)
tuple2.int
tuple2.string
tuple2.bool
5.流程控制
5.1 if else
- 条件判断不需要加小括号,但是大括号不能省略
- if 后面的条件判断只能是Bool值,和OC中的
nil
,以及非0为真
等判断都不再适用
5.2 while 和 repeat
-
while 循环和OC中没有差别,只是也是可以省略条件判断的小括号
-
repeat 相当于OC中的 do-while,语法如下
var num = 10 repeat { num -= 1 print("\(num)") } while num > 0
5.3 for
- Swift中去掉了
++ --
运算符吗,通过+= -=
取代 - 区间运算符
- 闭区间运算符:a...b 表示取值>= a 且 <= b
- 半开区间运算符: a..<b 表示取值>= a 且 < b
- 单侧区间:让区间炒一个方向无限延伸,当起配合数组使用的时候,会默认在数组的界限内
- [a...] 表示大于>= a的一些列值
- [...a] 表示大于<= a的一些列值
- [..<a] 表示大于< a的一些列值
- 比如数组array有5个值,那么 array[2...] 表示取值下表为 2 到 4 的3个元素,不能越界,如果越界一样会崩溃
// 区间运算 var array = [1,2,3,4,5,6,7] for i in array[2...] { print(i) } // 打印结果为 3 4 5 6 7
contains
方法,用以判断当前区间是否包含某个值
let range = 2...8 range.contains(2) // true range.contains(9) // false
-
区间类型
-
闭区间是ClosedRange<T>类型
let r1: ClosedRange<Int> = 1...3
-
半开区间是Range<T>类型
let r2: Range<Int> = 1..<3
-
单侧区间是PartialRangeThrough<T>类型
let r3: PartialRangeThrough<Int> = ...3
-
-
字符串区间值 上面介绍的都是一些Int类型,区间类型也可以用字符串或者字符类型,但是只能表示一系列值,不能用for-in去遍历
-
带间隔的区间值
- for 循环去掉了比较经典的三段论
(int i=0; i<= N; i++)
取而代之的是类似于for..in
的一种拓展,通过区间预算符进行替换- 对于通过需要设定一个区间去取值的时候,即实现三段论的方式
for i in 2...5 { print(i) } // 打印结果为 2 3 4 5 for i in 2..<5 { print(i) } // 打印结果为 2 3 4
- 也可以直接for in 一个数组
// 区间运算 var array = [1,2,3,4,5,6,7] for i in array[2...] { print(i) } // 打印结果为 3 4 5 6 7 ``` * 数组配合单侧区间元素符,上边已经讲过了
- 对于通过需要设定一个区间去取值的时候,即实现三段论的方式
5.4switch
基本用法差不多,与C和OCswitch的不同是
case
和default
后面至少要有一条语句,且不可以用;
代替,如果不想做任何操作,可以写一句break
case
和default
下面的语句不能写大括号{},OC中的多行代码的时候需要括起来- 默认可以不写
break
,语句也不会贯穿执行,OC中不写break
会贯穿 - 实现贯穿的两种方式
- 使用
fallthrough
替代OC中的break
的位置,当前条件就可以贯穿执行 - 将要贯穿的条件全部写到一个
case
条件后面
- 使用
case
或者case
+default
必须要覆盖了switch
后面所有的值,如果覆盖不到,编译就会报错,比如switch后面的值有5种类型,只case了3种类型,就会报错,不如不需要case 所有情况,就配合default
+break
使用- switch 后面的值类型,不再只限定为
Int
类型,也支持字符和字符串类型,甚至是无类型的枚举,无类型的枚举在后续文章中会专门进行介绍 case
后面值也可以使用刚才提到区间值 和 元组
-
值绑定
:就是在case一个条件的时候,允许部分将一个值的部分进行匹配,剩余部分当做一个变量,进行后续的处理,比如在元组中let point = (1,0) switch point { case (let x,0): print("在X轴上值为\(x)") case (0,let y): print("在y轴上值为\(y)") case (let x,let y): print("在x轴上值为\(x) - \(y)") } /-------console-------/ 在X轴上值为1
-
where
case 还可以写成一个条件表达式,where
可以表示上面的值绑定中的变量进行一些比较,或者处理//switch where let p2 = (1,2) switch p2 { case let(x,y) where x == y: print("x == y") case let(x,y) where y > x: print("y > x") case let(x,y) where y < x: print("y < x") default: break } /-------console-------/ y > x
-
where - for
作为遍历时,作为对元素进行一些条件判断
// for where
let list = [1,2,3,4,5,6,7,8]
for item in list where item % 2 == 0 {
print(item)
}