基础特性
可空类型的操作符
左边
|
右边
|
返回
|
使用示例及场景
|
|
?
|
可空实例绑定
if let va = vb, vc=va{
}
可空链式调用
va?.uppercased()
va?.append()—原地修改
|
|||
!
|
隐式展开可空类型(是可空类型的一种)
|
|||
??(nil合并运算符)
|
可空类型
|
对应的非可空类型
|
nil返回右边,否则左边的展开值
|
数组:
声明方式一:
var alist: Array<String>
声明方式二:
var alist: [String] = ["q","p","r"]
数据比较时,注意是有序的。
字典:
var dict1:Dictionary<String, Double> = [:]
var dict2 = Dictionary<String, Double>()
var dict3:[String:Double] = [:]
var dict4 = [String:Double]()
要点:
当用key去获取value时,如果没有值则返回的是value类型的可空类型。
技巧一:循环
for (key,value) in movieRatings{
}
技巧二:转换到数组
let va = Array(movieRatings.keys)
集合:
var groceryBag = Set<String>()
groceryBag.insert("qifwef")
for food in groceryBag{
print(food)
}
要点:不会重名,相当于distinct
有uion的方法针对两个set的取交集
有contain的方法针对set来判断元素存在
有intersection(_:)来找出两个set的都存在的元素set
有isDisjoint方法来判断两个set是否存在交集
函数:
func fname(外部参数名 内部参数名:[inout]类型)->(返回)类型{
return 返回值
}
注意:内部参数名就已经是显示参数名了,即在没有外部参数名时,使用函数时可以带着。而外部参数名更多是用于介词的辅助。当参数列表中有任一参数提升了层次,即用上了外部参数名,那么,有一个_符号是用来应付无关紧要的那个参数的外部参数名。如果要熟练玩味这两类参数名,一定是在使用中玩味出应用场景的概念。内部是函数微观算法层。外部是类型和指代层。
- 变长参数
上面的变成<类型…>
- 默认参数
直接用="defaultvalue"即可
- in-out参数
调用时实参要加&修饰,以示要在函数内修改。
- 多个返回值时
-> (returnvalue1: [Int], returnvalue2:[String])
- guard语句
func …
{
guard let mv = name.middle else{
print("out func here.")
return
}
print(mv)
}
gurard守护的条件不足时提前返回。mv的可空类型没有值,或者为nil时,执行打印out func here.和返回。
如果守护的条件“不尴尬”时,就后面用其值了,print(mv)。
- 闭包(高阶函数)
闭包通俗来说就是{},有时是嵌套在函数内的函数。但更多的指把函数为参数传值给函数和从函数内返回函数类型,注意返回是引用类型,传入可以匿名技巧。
高阶函数是至少要接受一个函数作为输入的。如:
数组的sorted(),map(),filter(),reduce()方法。在swift中sorted既可以用传入参数的语法:
vv.sorted(by: sortAscending)
也可以使用匿名函数法。即闭包表达式的应用:
vv.sorted(by:{(i:Int,j:Int)->Bool in
return i<j
})
利用类型推断,再进化一下:
vv.sorted(by:{(i,j in i<j})
最终版本:
vv.sorted(by:{$0 < $1})
因为数组的元素类型是默认的了。
对象特性/技术
枚举:
要点:第一次创建枚举的变量就必须要初始化。
枚举类型可以没有原始值,即一定要归成Int类型。当然也可以用原始值,并指定初始值。不局限成Int类型的。
细分应用场景:
有限的
计算的,可修改
技巧:
mutation func XXX…
说明这个函数会修改对象中的值。
结构:
细分应用场景:
无限的
计算的,要修改,简单继承扩展
无复杂关联操作的
技巧:
mutation func XXX…
说明这个函数会修改对象中的值。
static func XXX…
说明这个函数是类型方法
类:
细分应用场景
无限的
计算的,要修改,要控制继承及可见性
复杂关联,可见性的
总之,继承,封闭,多态。
技巧:
[final] [override/static] [class] func XXX…
说明final class == static符号,关闭子类重写本方法的意思。所以class和static两个符号在结构和类中是不同涵义的。(结构中没有class关键字)
属性:
- 嵌套属性
类作用域中的枚举或结构,比如某一个枚举Size(类的接下来的属性会用到。)
- 存储属性
此类型属性必须有值,默认也可,后初始也可,这主要和下面的类型区别。只读的存储类型==常量
- 惰性存储属性
lazy var townSize:Size = {
switch selft.population{
case 0…10_000:
return Size.small
….
}
}()
注意:后面还有一对小括号,就说明这是一个运行得出的属性。但依赖的population是一个存储属性。类一初始化就已经给定,所以,算法也是一并初始就定了。而且,后面不会重新计算了。这块取义依赖的成分大于惰性。
- 计算属性
var townSize:Size {
get{
switch selft.population{
case 0…10_000:
return Size.small
….
}
}
set(){
}
}
- 属性观察者
var population = 5_422 {
didSet(oldpopulation){
}
}
- 类型属性
此类属性的值在同类型实例间共享。但必须有默认值(原因是没有初始化方法的)。
在类中的可以用class修饰来让子类继承覆盖,也可以用static来禁止覆盖。
适合将没有入参的行为改写成类型属性。
- 访问控制
描述
|
对who可见
|
能继承使用
|
|
open
|
|||
Public
|
|||
internal(默认)
|
|||
fileprivate
|
|||
private
|
初始化方法
-
结构体的默认初始化
var myTown = Town()
结构体的成员初始化
var myTown = Town(population:10_000, numberOfStoplights:6)
- 结构体自定义初始化
委托初始化(在结构体中称为这个,在类中同义但是称为便捷初始化)
init(){
self.init()
}
- 类的初始化(在类的继承场景中)
指定初始化
init(){
//初始化本类引入的属性
super.init()//调用父类中的初始化方法
}
便捷初始化
convenience init(){
selft.init()//本地的初始化,其中也可能调用指定的初始化,层层初始。
}
必需初始化
父类中要求
required init
子类中实现,关键字包括了Overrider的意思。
required init
反初始化方法
deinit{
}
高级特性
协议
枚举,结构体,类都可遵守协议,同时协议也可以继承,也可使用&来组合(用于传递参数)。可以理解它为是样貌。
protocol Velocity{
}
异常
func getNumber() throws -> Int{
…
throw 类中枚举的异常值
}
使用上面的函数时便可try getNumber()
或者在外层包裹:
do{
try get…
anotherfunc()
}catch Parse.Error.unexceptedEndOfInput{
}catch{
}
扩展
注意针对是类型,且是可以针对协议的。强大的冒汗了。可以理解成它是样式
typealias Velocity = Double
extension Velocity {
}
泛型和协议扩展的争论
泛型是固化一种模式算法,而扩展是让对象本身增量元素或行为,即样式或样貌。
所以,会用泛型,你要先具备知识,知晓有了某种前人栽的树,即知道已经有满足的可用的公共泛型函数了。
而用协议扩展,你就要自己栽树,但只给自己用在自己的地里。