swift类型
整数
有符号和无符号类型两种,根据有效位又有8 16 32 64的区别,Int、UInt8等,Int是一个语法糖,Xcode会根据运行平台来决定是32位还是64位,所以在进行存储型属性赋值时可以不用显示声明数据类型(计算型需要)如let count = 10,因此如果需要制定特定类型那么声明一个值时最好是加上其类型为好。
数值范围直接调用(.min)和(.max)即可
浮点数
根据精度有Float和Double两种,前者是32位浮点,有效精度6位,后者64位浮点,有效精度15位,在两者都符合时,Double最好。这也是let money = 3.25时默认推断为Double类型的原因
补充:
1.因为swift是强类型语言,因此一个函数如果参数制定为String,传入一个Int类型则会报错。当然特殊情况下如果需要适配多种类型,则有泛型和父类等选择可用。
2.数值型字面量,主要是进制显示,如二进制,八进制,16进制以及默认的十进制
( 浮点字面量可以是十进制(没有前缀)或者是十六进制(前缀是 0x )。小数点两边必须有至少一个十进制数字(或者是十六进制的数字)。十进制浮点数也可以有一个可选的指数(exponent),通过大写或者小写的 e 来指定;十六进制浮点数必须有一个指数,通过大写或者小写的 p 来指定 )
一个十进制数,没有前缀
一个二进制数,前缀是0b
一个八进制数,前缀是0o
一个十六进制数,前缀是0x
3.数值转换,如Int8转为Int,一般是低位数类型网高位数转换,如果是Int转Int8则会报错,原因就是有效位数问题,联想OC中的数值溢出。swift为了防止类似问题,在类型使用时会做检查,如果是动态计算时,则还是会有这个问题存在,因此才会首选推荐使用Int和Double类型
布尔类型
逻辑常量,true和false两个,OC以前的布尔值并不纯粹,因为可以被强转,,,
元组
这个就是可以放不同类型的数组,并且元组可以作为函数返回值,这样OC以前想要在一个方法中返回多个数值只能通过block或者返回一个封装好对象或者是字典的痛苦就没有了,swift中很优雅的使用元组返回即可,如下:
let http404Error = (404,"Not Found")
元组定义时可以加上命名,如let http200Status = (statusCode:200, description:"OK")
数组:
OC中时NSArray,swift中时Array,NSArray可以直接互转Array,使用as即可,这个是官方做的处理
swift数组的类型: [Int] 或者 Array
swift中Array创建有多种方式:
var someArray1 = [String](repeatElement("123", count: 3)) //类型是字符串,默认是123 长度是3
var someArray2 = ["123","123","123"]
var someArray3 : [String]=["123","123","123"]
var emptyArray = [Int]()
补充:
1.数组类型如果是var来声明则是可变数组,let声明则是不可变数组
2.数组的操作方法(.count .first .last .isEmpty .min() .max() .contains() .index(of:) )
3.数组的遍历
4.开闭区间 0...5说明是0到5,包含5; 0..<5则是0到5,不包含5,数组中常用到numbers[2..<numbers.count]
5.数组遍历,和java的foreach遍历一样
for index in 0..<numbers[index] {
}
for number in numbers{
print(number)
}
for (index, vowel) in vowels.enumerated() {
//遍历数组索引和元素 print("\(index+1): \(vowel)")
}
6.对可变数组的操作(var声明的)
.append() .insert() removeLast() removeFirst() removeAtIndex() remove(at:) removeRange() removeAll() +=(这个是操作符重载)
7.NSArray是一个类,Array是一个结构体如图:
字典
swift字典Dictionary和OC的NSDictionary也是可以直接转换,使用as即可。
swift字典类型Dictionary<String, String>()或者 [String: String]()
创建方式多种:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var dict1 : [String: NSObject] = [String: NSObject]()
let dict2 = ["name":"why","age":18]
var dictM = [String: AnyObject]()
补充:
1.可变与不可变是通过声明时var或者let来判定的
2.字典操作方法(dictM["name"] ="why" .removeValueForKey() )
3.字典遍历
for key in dictM.keys {
print(key)
}
for value in dictM.values {
print(value)
}
for (key, value) in dic1 {
print(key)
print(value)
}
4.字典合并,不可想数组一样直接 +操作,切记切记
for(key, value)in dic2 {
dic1[key] = value
}
5.和数组一样,swift字典也是一个struct,NSDictionary是一个类
6.struct和enum是数值类型,所以传递时都会被拷贝一份如下图:
arr2和arr1并不是指向一个数组,arr2是直接拷贝了一份数据过去,因而编译器也给了提示,arr1并没有进行可变操作,使用let声明即可。字典也是一样的,这个和OC中的NSArray使用方式有区别,切记切记(因各自的本质不同,一个是对象,一个是struct)
结构体:
swift中类和结构体联系很密切,也可以在大多数场景进行互换使用,例如数据解析的model可以使用对象也可以使用struct来进行使用。都有如下特性:
1.定义属性用于存储值
2.定义方法用于提供功能
3.定义下标操作使得可以通过下标语法来访问实例所包含的值
4.定义构造器用于生成初始化值
5.通过扩展以增加默认实现的功能
6.实现协议以提供某种标准功能
不过swift中更偏爱使用struct来替代对象的使用,这一点和go语言很像。struct值类型,分配在内存中,对象分配在堆中。因而go作为服务器语言,优先考虑内存中的特性,因为更快。
栈是程序启动的时候,系统事先分配的,使用过程中,系统不干预;堆是用的时候才向系统申请的,用完了需要交还,这个申请和交还的过程开销相对就比较大了。
栈是编译时分配空间,而堆是动态分配(运行时分配空间),所以栈的速度快
swift中struct不可继承,赋值时是浅拷贝,也就是直接复制一份同样的数据,对象赋值时是深拷贝,直接传递指针过去。此外如果要修改struct中属性,需要添加mutating方法如:
mutating func changeData(vaule: Int) {
self.Data= vaule
}
swift中提供了恒等判断:因为类是引用类型,有可能有多个常量和变量在幕后同时引用同一个类实例。值类型用不到这些如枚举,结构都是值类型,不是对象类型
=== 等价于”表示两个类类型(class type)的常量或者变量引用同一个类实例
== 等于”表示两个实例的值“相等”或“相同”,判定时要遵照设计者定义的评判标准
枚举:
枚举为一组相关的值定义了一个共同的类型,使你可以在你的代码中以类型安全的方式来使用这些值。也就是枚举中各值可以是不同类型,这个和OC枚举是不一样的,此外枚举也对每个case的值做了一层包装,要直接访问原始值需要.rawValue来进行访问,也可以对rawValue进行重写来确定如何返回原始值
如图:
声明:
enum CompassPoint{
case north = 1
case south
case east
case west
}
也可以预先填充值如
补充:
1.关联值如下:
enum Barcode{
case upc(Int,Int,Int,Int)
case qrCode(String)
}
“定义一个名为Barcode的枚举类型,它的一个成员值是具有(Int,Int,Int,Int)类型关联值的upc,另一个成员值是具有String类型关联值的qrCode。”
使用时可以是:
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
2.原始值:
枚举成员可以被默认值(称为原始值)预填充,这些原始值的类型必须相同;
原始值可以是字符串,字符,或者任意整型值或浮点型值。每个原始值在枚举声明中必须是唯一的
enum ASCIIControlCharacter:Character{
case tab ="\t"
case lineFeed ="\n"
case carriageReturn ="\r"
}
原始值和关联值是不同的。原始值是在定义枚举时被预先填充的值,像上述三个 ASCII 码。对于一个特定的枚举成员,它的原始值始终不变。关联值是创建一个基于枚举成员的常量或变量时才设置的值,枚举成员的关联值可以变化
在使用原始值为整数或者字符串类型的枚举时,不需要显式地为每一个枚举成员设置原始值,Swift 将会自动为你赋值
3.递归枚举
它有一个或多个枚举成员使用该枚举类型的实例作为关联值。使用递归枚举时,编译器会插入一个间接层。你可以在枚举成员前加上indirect来表示该成员可递归
enum ArithmeticExpression{
case number(Int)
indirect caseaddition(ArithmeticExpression, ArithmeticExpression)
indirect casemultiplication(ArithmeticExpression, ArithmeticExpression)
}
可选类型:
用来处理值可能缺失的情况,联想OC中的对象nil判断和数值的NSNotFound,swift则将两者合一,直接使用optical包含了两种情况
Swift 中,nil 不是指针——它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为 nil,不只是对象类型
在 Objective-C 中,nil 是一个指向不存在对象的指针
补充:
1.可选类型强制解析( !),使用强制解析先判断是否空,否则易崩溃
2.可选绑定,主要是用来简化判断代码
if let constantName = someOptional {
statements
}
3.在if条件判断中如果是多个条件用(,)号隔开,则表明是&&同义
if letfirstNumber =Int("4"), letsecondNumber =Int("42"), firstNumber < secondNumber && secondNumber <100 {
print("\(firstNumber)<\(secondNumber)< 100")
}
如下图:
前者count<3是false, 后者abs <3为true,但是结果是打印了下面的,因此逗号隔开与&&同义,只是一个简单写法而已。
这个真想吐槽,写法太自由了容易导致代码阅读困难
4.隐式解析可以减少判断代码,如session?.riskFunc(),这样相当于对session做了一次解析并且判断,只有session不为空时才会执行后面的riskFunc()方法
类型别名:
typealias和OC的typedef一样,别名,方便代码可读性。常用用法有block命名,对系统空间进行别名处理,这样来进行第三方库等的库内控件名字区分如图:
kingfisher的源码20180412