1、协议关键字protocol
与objc的协议区别,多了计算属性支持,不过计算属性也可以理解成方法。
某个类型符合协议,或者说遵循某个协议,其语法与继承一样,都是类型名称后 +冒号+协议名称。
当我们添加协议后,会有错误警告,通过Fix修复错误会自动把协议需要实现的方法自动列出来,不需要我们一一写。
所有类型都支持协议,枚举,结构,类都可以符合协议
与objc一样,可以符合多个协议
与objc不一样的地方是,swift的协议支持继承,还可有多继承。
如果协议中声明的方法在值类型实现中需要修改self,注意要方法前标记mutating。
2、assert与precondition的区别是,assert在release版本被编译器优化删除,而precondition在debug版本和release版本效果一致
3、Swift在可能抛出异常的函数声明中加上关键字throws,该关键字在函数参数与->之间。
遇到可能会抛出异常的方法,必须要用do catch语法来捕获异常。
do {
try//用try关键字标记存在异常的方法
} catch {
//在这里我们可以
}
Swift允许二次抛出异常,在调用可能存在异常的方法时,用try标记,但是可以不用do catch,而是让当前方法声明上标记throws达到可以支持二次抛出异常。
总结如下:必须用try标记每次调用可能抛出错误的函数,而任何try标记的调用必须要么在do catch语句块内,要么在一个本身被标记为throws的函数内。
不过也有个例外,可以在try后面跟随感叹号。与强制展开可空实例一样,一旦出现错误程序就会崩溃。该用法谨慎使用,少用。
还有第三种情况,可以用try? 调用一个可能抛出异常的函数,得到函数原本的返回值对应的可空类型返回值。发生错误的时候忽略错误而不触发陷阱。常用于有后备函数可用,且配合guard关键字使用。
4、swift对应objc中的category的语法关键字是extension,枚举、结构体、类都支持extension。其用法基本跟objc的category类似,都不支持存储属性,但是支持计算属性,支持protocol,支持增加方法,支持添加嵌套类型,支持新初始化方法。
5、swift把c++中的模板特性引入,称为泛型。其语法如下
type TypeName
}
用法:
var a = TypeName ()
枚举、结构体、类和函数都支持泛型。
在实现泛型的时候,对于一些无法预知的类型,其某些功能不知道是否支持的情况下,通过增加泛型约束来实现。有两种类型约束:一种是类型必须是给定类的子类,还有一种是类型必须符合一个协议或者协议组合,具体语法:尖括号里的类型+冒号+协议。
协议是不可以直接支持泛型的,不过协议支持一个相关特性:关联类型,参考如下:
protocol IteratorProtocol {
associatedtype Element
mutating func next()-> Element?
}
protocol Sequence {
associatedtypeIterator: IteratorProtocol
func makeIterator()-> Iterator
}
在实现泛型的时候,有可能一个泛型约束不够,还需要where子句来进行更多的约束。代码参考:
mutating func pushAll (_ seq:S)where S.Element==Element {
for item in seq {
self.push(item)
}
}
关于多态的特性,用继承,或协议,或泛型都可以支持。
6、swift新特性,除了枚举、结构、类支持extension扩展,协议也可以进行扩展,可以添加有实现的计算属性和方法,只是不能添加存储属性。
之前提过协议是支持继承,且多继承,在实践过程中,我们给一个协议A补充从另外一个协议B继承,这个时候我们发现我们已经有多个实现是从符合A协议的,正常情况,需要我们在每个实现中补充B协议的实现。但是有了协议扩展extension的特性,我们不需要这么做,仅仅通过extension A来补充B的方法实现则可。当然,如果我们硬是要在单个实现中补充B协议的实现是可以的,且其优先级会高于协议的扩展,会覆盖协议的扩展方法。
有个地方要小心了,如果我们单纯扩展协议增加一个计算属性或方法,又在具体类型实现了同名的计算属性和方法,这些方法和计算属性因为不是协议必须的,所以会有预期不到的结果,编译器并不会检测实际的类型,而是遵循我们我们提供的类型信息。
7、swift内存管理采用ARC(自动引用计数)
默认情况下创建的类实例是强引用,可用关键字week声明为弱引用。弱引用必须是var声明,且可空。
在实际应用中,注意避免循环引用。在使用闭包的时候也要注意循环引用。闭包增加分逃逸闭包和非逃逸闭包两个概念,通常闭包作为参数传给函数时,是非逃逸闭包,这种闭包编译器可以确定不会造成循环引用,而作为类型的属性这种闭包是逃逸闭包,这种闭包就容易引起循环引用。在使用的时候要使用捕获列表来避免循环引用。捕获列表语法如下:[weak self]:
注意,混合使用逃逸闭包和非逃逸闭包是会编译错误的,如果要避免错误,可以用
@escaping属性来修复这个错误。
Swift是不可以访问实例的引用计数,但是有个函数(isKnownUniquelyReferenced)可以判断一个实例是否是对某个实例的唯一引用。