空合并运算符
var count:Int? = 10
var value:Int
/// 空合并运算符 第一个操作数必须为optional 如果不为nil责将进行拆包操作
print(count ?? 0) 和 三目运算符 print(count != nil ? count! : 0) 结果一样
结果为:10
元祖
/// 定义元祖
var student:(String,Int,Float) = ("kakaxi",20,185.0)
/// var stu:(name:String,age:Int,height:Float) = ("kakaxi",20,185.0)
print(student.0)
/// 将元祖进行分解 分解命名时使用_忽略命名字段
var (name,_,_) = student
print(name)
结果为:kakaxi
数组
声明一个十个元素相同的数组
var array = [String](repeating: "helllo world", count: 10)
var arrList = [0,1,2,3,4]
遍历数组的不同方式
for item in arrList {
print(item)
}
0
1
2
3
4
for item in arrList.enumerated() {
print(item)
}
(offset: 0, element: 0)
(offset: 1, element: 1)
(offset: 2, element: 2)
(offset: 3, element: 3)
(offset: 4, element: 4)
for index in arrList.indices {
print(arrList[index], separator:"")
}
0
1
2
3
4
字典
var dicts:Dictionary<Int,String>
dicts = [1:"1",2:"2"]
print(dicts)
结果为:[2: "2", 1: "1"]
Set
集合(Set)
集合(Set)特点:无序、唯一性、集合操作、快速查找。
集合的数据显示和数组是一样的,所以必须显示的声明Set集合!不然!就是数组!
// 初始化A、B、C三个集合
var A:Set<String> = ["A", "B", "C", "D"]
var B:Set<String> = ["C", "D", "E", "F"]
var C:Set<String> = ["B", "B", "C"]
// 上面Array、Dictionary动态初始化有四种,这里面只有两种
var set1 = Set<String>()
var set2:Set<String> = []
// 集合的数量
A.count
// 集合第一个元素,因为集合的无序性,它的第一个元素没有意义
A.first
// 集合是否为空
A.isEmpty
// 向集合中插入一个元素
A.insert("C")
// 删除集合中的元素
A.remove("C")
// 判断集合中是否包含某个元素
A.contains("A")
// 遍历集合
for index in A {
index
}
运算符
///通过~=运算符来检查某个数字是否包含在范围中
var range = 0...10
print(range~=8) true
while和repeat-while 条件循环结构
当 i 大于等于10的时候跳出循环
var i = 0
while i < 10 {
print("while",i)
i += 1
}
repeat while 循环
先执行循环体,在进行条件判断 和 OC 中的 do - while功能基本一致
var j = 0
repeat{
print("while",j)
j+=1
}while j < 10
流程跳转语句
swift中提供的流程跳转语句主要有:continue、break、fallthrough、return、throw、guard
continue: 语句用于循环结构中,作用为跳过本次循环,直接开始下次循环
break:中断语句,也可以用于循环结构中,和continue语句不同,break语句会直接中断包含它的循环结构
fallthrough:语句是swift中特有的一种流程控制语句,可以再中断语句中继续执行下面的语句
例如:
var i = 3
switch i {
case 1...3:
print("switch")
fallthrough
default:
print("default")
}
结果为:switch default
如果不加fallthrough 结果为:switch
return: 用于返回结果值,或者用于提前结束无返回值类型的函数
throw: 语句用于抛出异常,抛出的异常如果不进行捕捉处理,也会使程序中断
guard - else: 是Swift2.0之后新加入的一种语法结构,Swift团队创造它的目的在于是代码结构和逻辑更加清晰
func normalFunc(param:Int){
if param <= 0 {
return
}
print(param)
}
func fuardFunc(param:Int){
guard param > 0 else {
return
}
print(param)
}
声明函数
有参数有返回值
func compare(param1:Int,param2:Int)->Int {
return param1 + param2
}
var add = compare(param1: 10, param2: 20)
print(add) 30
func search(searchID:Int)->(success:Bool,data:String){
let reust = true
let data = "数据实体"
return(reust,data)
}
if search(searchID: 1000).success {
print(search(searchID: 1000).data) 数据实体
}
函数的参数可以传也可以不传(设置默认值)
func myFunc(param1:Int,param2:Int = 10)->Int {
return param1 + param2
}
print(myFunc(param1: 8)) 18
print(myFunc(param1: 10, param2: 40)) 50
函数可以多参数,也可以多个不确定参数
在参数后面添加...
func funcParams(param:Int...)->Int{
var sum = 0
for count in param {
sum+=count
}
return sum
}
print(funcParams(param: 10,20,30,40,50)) 150
声明一个函数变量
var addFunc:(Int...)->Int
addFunc = funcParams
print(addFunc(100,200)) 300
函数重载 相同方法名 参数返回值不同
func addFunc(param1:Int,param2:Int)->Int{
return param1 + param2
}
func addFunc(param1:Double,param2:Double)->Double{
return param1 + param2
}
func addFunc(param1:String,param2:String)->String{
return param1 + param2
}
闭包
闭包标准结构:
{(参数列表)-> 返回值 in 闭包体}
首先闭包最外层由大括号包围,内部由闭包关键字in来进行分割,关键字in前面为闭包结构的参数列表和返回值,其书写规则与函数一致,in关键字后面为闭包体,用于实现具体功能
let closures = {(param:Int)->Int in
return param * param
}
自定义运算符
prefix operator ++
prefix func ++(param:Int)->Int
{
return param + 1
}
枚举
enum Season {
case spring
case summer
case autumn
case winter
}
let season = Season.spring
func switchFunc(){
switch season {
case .spring:
print("spring")
case .summer:
print("summer")
case .autumn:
print("autumn")
default:
print("winter")
}
}
switchFunc() spring
结构体
swift 既可以声明属性也可以定义方法
struct Car {
var price:Int
var brand:String
var petrol:Int
mutating func Drive(){
if petrol > 0 {
print("driving")
}else{
print("drived")
}
}
}
var car = Car(price: 100000, brand: "宝马", petrol: 10)
car.Drive() // driving
类
在创建类时,使用final关键字 其类不可以被继承
使用final声明属性时,其属性不可以被子类使用
指定构造方法与遍历构造方法
对于类来说,构造方法有指定构造方法和便利构造方法之分。 指定构造方法的官方名称为Designated,遍历构造方法为Convenience。
指定构造方法不需要任何关键字修饰,便利构造方法需要使用Convenience关键字来修饰。
关于指定构造方法和便利构造方法,Swift语言中有这样的规定:
1. 子类的指定构造方法中必须调用父类的指定构造方法。
2. 遍历构造方法中必须调用当前类的其他构造方法。
3. 遍历构造方法归根结底要调用到某个指定构造方法。
// 创建一个类作为基类
class BaseClass {
// 提供一个指定构造方法
init() {
print("baseClass Designted")
}
// 提供一个便利构造方法
// 便利构造方法必须调用当前类中的其他构造方法,并最终调用到指定构造方法
convenience init(param:String) {
print("BaseClass Convenience")
/// 进行指定构造方法的调用
self.init()
}
}
/// 创建一个BaseClass的子类
class SubClass: BaseClass {
// 覆写指定构造方法中必须调用父类的指定构造方法
override init() {
super.init()
}
// 提供两个便利构造方法
convenience init(param:String) {
// 最终调用到某个指定构造方法
self.init()
}
convenience init(param:Int) {
// 调用一个便利构造方法
self.init(param: "Swift")
}
}
var obj = SubClass()
print(obj) // baseClass Designted conditation.SubClass
引用计数
Swift中语言中的数据传递分为两种,即值类型的数据传递和引用类型的数据传递
对于值类型的数据传递,其采用的是完全复制的原理,因此原数据的销毁与内存的释放并不会影响新数据,
新数据占用的内存会在它本身作用域结束时释放。
if true {
var a = 0
if true {
var b = 1
a = b
}
// 此时变量b所占内存被释放
}
// 此处变量a所占内存被释放
引用数据类型的数据传递就复杂一些,我们知道引用类型的数据传递并不会完全复制原数据,
而是通过要引用的方式对原数据进行访问,因此无论一个类实例被多少个变量所承载,其真正所访问的内存都是同一个地方。
if true {
var a = TestClass()
if true {
var b = a
}
// 此处变量b已经不存在,但是TestClass实例依然占用内存, 没有释放
}
// 此处变量a已经不存在,也没有其他变量引用TestClass实例,该实例将调用deinit方法,其所占内存被释放
循环引用及其解决方法
循环引用一直是初级开发者编程的噩梦。对类实例进行不当的引用会造成内存泄露,内存泄露积累到一定程度就会给应用程序带来灾难性的后果。
class ClassOne{
deinit {
print("ClassOne deinit")
}
}
class ClassTwo{
/// ClassTwo 类中有一个ClassOne类的属性
var classOne:ClassOne?
init(classOne:ClassOne?) {
self.classOne = classOne
}
deinit { /// 析构方法 相当于OC中的dealloc
print("ClassTwo deinit")
}
}
var classOne:ClassOne? = ClassOne()
var classTwo:ClassTwo? = ClassTwo(classOne: classOne)
/// 此时ClassTwo类中的classOne属性依然在引用classOne实例,因此classOne实例所占内存没有释放
classOne = nil
/// 此时classTwo 被释放,classTwo中的属性也都被释放,不在有谁引用classOne,classOne实例也被释放
classTwo = nil
结果为:
ClassTwo deinit
ClassOne deinit
**上述代码十分健康,两个类都被释放**
class ClassOne{
var cls:ClassTwo?
deinit {
print("ClassOne deinit")
}
}
class ClassTwo{
/// ClassTwo 类中有一个ClassOne类的属性
var cls:ClassOne?
init(cls:ClassOne?) {
self.cls = cls
}
deinit {
print("ClassTwo deinit")
}
}
var classOne:ClassOne? = ClassOne()
var classTwo:ClassTwo? = ClassTwo(cls: classOne)
classOne?.cls = classTwo
classTwo = nil
classOne = nil
**上述两个类都没有被释放,代码中已将将classOne和classTwo都置为nil,但其所占据的内存将无法释放,这便是循环引用最常见的场景**
Swift 语言中提供了弱引用关键字(weak)来处理这样的问题;weak 关键字的作用是在使用这个实例的时候并不保有次实例的引用
(普通的引用类型数据在传递时会使实例的引用计数加1,使用weak关键字修饰的引用类型数据在传递时不会使引用计数加1)
将ClassOne中的属性 使用weak 声明:
weak var cls:ClassTwo?
结果为:
ClassTwo deinit
ClassOne deinit
扩展:
**
弱引用还有一个特点,其职能修饰Optional类型的属性,被弱引用的实例释放后,这个属性会被自动设置为nil,那么问题来了,如果开发中使用到的属性是非Optional值类型的,又恰巧出现了循环引用的场景,开发者该如何处理呢?其实Swift语言中还提供了一个关键字(unowned 无主引用)来处理非Optional值类型属性的循环引用问题。
**
网友评论