最近看了一点关于swift的书籍,记录一些知识点。都是我自己的理解,可能会有些不准确的地方,请指出来,一起学习,感激不尽。
swift 3.1官方介绍地址
1.Assert: 断言
在Swift中,通过assert实现断言,assert可以帮助开发者比较容易的发现和定位错误,断言断定条件是true。通过声明一个断言来确保某个必要的条件是满足的,以便继续执行接下来的代码。如果条件满足了,那么代码像往常一样执行,如果不满足了,代码就停止执行了,应用也随之停下来了。 只是查找问题,在只有TRUE的情况才可以执行的代码位置 加上断言。。
断言的另一个优点是它是一个开发时的特性,只有在 Debug 编译的时候有效,而在运行时是不被编译执行的,因此断言并不会消耗运行时的性能。这些特点使得断言成为面向程序员的在调试开发阶段非常合适的调试判断,而在代码发布的时候,我们也不需要刻意去将这些断言手动清理掉,非常方便。
2.fatalError
fatalError 和断言有点类似。fatalError 是抛出一个异常,让程序结束。
fatalError的作用就是产生一个致命的错误,来终止程序。和断言的区别就是:在release环境下依然可以使用。
使用场景举例:父类有一个方法,要求子类必须实现,这时候就可以在父类方法中写上这个fatalError, 当子类没有实现这个方法,但是直接调用了这个方法时,就直接停止程序。
举个栗子:
我们定义了一个方法,但是不想让别人调用,但是又不得不暴露出来,这时候就可以使用fatalError了。
func methodMustBeImplementedInSubClass() {
fatalError("这个方法必须在子类中被重写")
}
//子类方法1
class subClass: CategaryViewController {
override func methodMustBeImplementedInSubClass() {
print("实现了父类的方法")
}
}
//子类方法1
class subClass1: CategaryViewController {
func someMethod() -> Void {
print("myself method,没有实现父类的方法")
}
}
//调用方法
let subclass = subClass()
subclass.methodMustBeImplementedInSubClass()
let subclass1 = subClass1()
//这里程序就会崩溃,因为没有重写父类方法。。fatalError触发了。。
subclass1.methodMustBeImplementedInSubClass()
3.procotol 代理。swift里procotol 方法默认都要实现。
代理的写法 注意:swift代理的方法都必须要实现,不然会报错。
// 对于需要结构体和枚举遵守的协议方法需要在前面添加mutating
参见:UITableViewDataSource代理,当你继承了这个代理,但是还没有实现其两个代理方法,程序就会报错;当你实现了cell和行数两个代理方法就ok了。
直接类似OC那样写是不可以的,没有类似weak属性,因为swift的协议可以给除了可以被class遵守,enum和struct也可以遵守。
1、在代理前面加@objc,但是这样可能会出现兼容OC的问题,在前面加上@objc 方法名前加:@objc optional,没加的默认都是要必须实现的。带有@objc关键字的协议只能被OC类,或者带有@objc关键字的类遵守,结构体和枚举都不能遵守.
2、在协议后面加上:class,限定整个procotol只能有class实现。 枚举和结构体不可以实现。。
protocol CustomCellDelegate: class {
required func method()
}
//另外一种可选实现方案:swift里的协议可选方法实现,使用扩展的方式
//定义个协议
protocol OptionalProtocool {
//默认三个协议方法是都要实现的
func opotionalMetod()
func necessaryMethod()
func anotherOptionalMetod()
}
//扩展协议 将父协议的两个方法已经实现,所以遵守协议的类,可以不实现这个协议已经实现的方法
extension OptionalProtocool {
func optionalMethod() -> Void {
print("optionalMethod")
}
func anotherOptionalMethod() -> Void {
print("anotherOpthionalMethod")
}
}
//类遵守了协议
class Myclass: OptionalProtocool {
//必须要实现的协议方法
func necessaryMethod() {
print("necessaryMethod")
}
//可选实现的协议方法 ,anotherOptionalMethod()这个方法没实现没有关系,因为已经在协议扩展里实现了。
func opotionalMetod() {
print("optionalMehod")
}
}
4.继承:
重写父类方法、属性需要在前面加override关键字
如果不想被子类重写,父类定义方法要在前面加上 final 关键字
子类也可以再次被继承,子类可以直接访问父类的属性、方法。
5.注释
xcode8 swift里有注释方法 统一为:///
再给方法等添加注释的时候,默认快捷键:cmd+alt+/ ,会直接生成注释代码 ;在调用方法时候,安装alt+点击,就能显示出注释的内容。
6.关于打印print方法
在swift里打印完成自动换行,假如不想换行,就要在最后一个参数那里设置为nil。
print(“print something ”, nil )
如果你想在打印一段文本中间就换行,只需添加\n即可:
eg: print(“123\n456”)
7.単例
class singleClass {
static let single = singleClass()
private init() {}
}
8.输出格式化
let b = 1.34343434
extension Double {
func formart(_ f: String) -> String {
return String(format: "%\(f)f",self)
}
}
//保留两位小数
let f = ".2"print("double: \(b.formart(f))")
9.数组遍历
//时候和OC数组遍历说再见了
let arr: Array = [1,2,3,4,5]
var result = 0
for (idx, num) in arr.enumerated() {
result += num
if idx ==2
{ break }
}
print(result) //1+2+3=6;
10.延时执行
//2s后执行某一个方法 几秒必须要加DispatchTime.now() + (n)s
let time: TimeInterval = 2.0
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) {
print("2s late print")
}
11.初始化顺序
与OC不同,swift的初始化方法需要保证类型的所有属性都被初始化。
保证当前子类实例的成员初始化完成之后才能调用父类的初始化方法。
init 构造器:如果子类必须要实现父类的构造器,父类要用require修饰init。可以自定义构造器,如果没有实现构造器,系统默认实现。
class Animals {
var name: String
init() {
name = "cat"
}
}
class Tigger : Animals {
let power: Int
override init() {
power = 100
//如果我们不用改变name的话,可以不用调用super.init(),因为这是初始化最后了,swift替我们完成了
// super.init()
// name = "tigger"
}
}
析构器:deinit 相当于OC中的dealloc。父类实现了析构器,子类也会继承下来,所有类簇只能有一个析构器。
12.属性观察 willset 和 didset
//属性观察 willset 和 didset
class MyClass {
let oneYearSeconds: TimeInterval = 365*24*60*60
var date:NSDate {
willSet {
let d = date
print("日期即将从\(d)shezhidao \(newValue)")
}
didSet {
//我们可以在这里做一些自己需要的事情,如果是不满足,可以将date设置为你想要的那个值
if(date.timeIntervalSinceNow > oneYearSeconds)
{
print”设定的时间太晚了,早点吧”
date = NSDate().addingTimeInterval(oneeYearSeconds)
}
print("日期已经从\(oldValue)设置至 \(date)")
}
}
init() {
date = NSDate()
}
}
13.改写log打印方法
//log的打印方式
func printLog<T>(_ message: T,
file: String = #file,
method: String = #function,
line: Int = #line)
{
#if DEBUG
print("类:\((file as NSString).lastPathComponent), 第\(line)行, 方法:\(method), \n内容: \(message)")
#endif
}
14.闭包
类似OC 暴露一个block 怎么实现??传一个闭包进来,参数和返回值一样就好了。 闭包可以看做OC的block。extension 相当于OC里的类别,但是比类别更强大、好写。
unowned 无主引用和 weak 弱引用。
15.错误处理
// 处理错误的几种方式: 1. 把错误传递给调用函数,然后使用do-catch语句处理错误
// 2. 将错误作为可选类型处理
// 3. 使用断言处理
// throwing函数: 在参数列表后面加throws,表示可以抛出错误
如果有返回类型,throws需要写在(->)前面, throw语句会立刻退出当前方法,相当于return
let throwClass = ThrowClass()
throwClass.num = 4
do {
try throwClass.throwFunc()
}catch CustomErrorType.errorReason1 { // 根据返回错误类型,执行这个{}
print("errorReason1") // errorReason1
}catch CustomErrorType.errorReason2 {
print("errorReason2")
}catch { // catch没有指定类型,那么可以匹配任何错误
print("errorReason3")
}
- defer语句
defer语句在异常抛出前,通常需要做一些操作,比如关闭文件,手动释放内存等,这些就可以在defer语句中执行
// defer语句会在return,break,以及错误抛出之前执行
// defer语句可以有多个
// defer语句必须要在throw语句前面才能执行
17.扩展 ——类似OC的分类.可以为已有的类 结构体 枚举或者协议类型添加新功能
// swift中可以扩展的功能: 1. 为已有类型扩展计算型实例属性和计算型类型属性
// 2. 为已有类型添加新的便利构造器
// 3. 为已有类型添加新的实例方法和类型方法
// 4. 为已有类型添加新下标
// 5. 为已有的类 结构体 枚举添加新的嵌套类型
// 扩展语法
class SomeClass { // 定义一个要扩展的SomeClass类
}
extension SomeClass: someProtocol { // 在类名前面添加extension关键字,冒号后面写协议名
// 扩展功能,协议实现写在这里
}
18.Api限定版本使用
//下面这个属性是 标明:只有在iOS10以后才可以用
@available(iOS 10, *) var animate : UIViewPropertyAnimator!
或者
@available(iOS 10, *)
var animate : UIViewPropertyAnimator!
//代码里判断哪个版本
if #available(iOS 10, *) {}
未完 暂时先写这么多,下篇继续。。。