swift学习笔记五

2017-01-09  本文已影响0人  crossyf

一、循环引用

1.swift提供两种方法来解决你在使用类的属性的时候所遇到的循环引用的问题:弱引用[weak self] 和无主引用 [unowned self]
弱引用和无主引用允许循环引用中的一个实例引用另一个实例而不保持强引用

2.弱引用
弱引用不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。声明属性或者变量时,在前面加上weak关键字表明这是一个弱引用。因为弱引用不会保持所引用的实例,即使引用存在,实例也有可能被销毁。因此,ARC 会在引用的实例被销毁后自动将其赋值为nil。并且因为弱引用可以允许它们的值在运行时被赋值为nil,所以它们会被定义为可选类型变量,而不是常量。

3.无主引用
和弱引用类似,无主引用不会牢牢保持住引用的实例。和弱引用不同的是,无主引用在其他实例有相同或者更长的生命周期时使用。你可以在声明属性或者变量时,在前面加上关键unowned
表示这是一个无主引用。无主引用通常都被期望拥有值。不过 ARC 无法在实例被销毁后将无主引用设为nil,因为非可选类型的变量不允许被赋值为nil。

重要:使用无主引用,你必须确保引用始终指向一个未销毁的实例。如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。

4.无主引用以及隐式解析可选属性

上面弱引用和无主引用的例子涵盖了两种常用的需要打破循环强引用的场景。
Person和Apartment的例子展示了两个属性的值都允许为nil,并会潜在的产生循环强引用。这种场景最适合用弱引用来解决。
Customer和CreditCard的例子展示了一个属性的值允许为nil,而另一个属性的值不允许为nil,这也可能会产生循环强引用。这种场景最适合通过无主引用来解决。

5.解决闭包的强引用

定义捕获列表
如果闭包有参数列表和返回类型,把捕获列表放在他们前面

lazy var someClosure: (Int, String) -> String = {
    [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
    // 这里是闭包的函数体
}

如果闭包没有指明参数列表或者返回类型,即它们会通过上下文推断,那么可以把捕获列表和关键字in放在闭包最开始的地方:

lazy var someClosure: Void -> String = { [unowned self, weak delegate = self.delegate!] in 
      // 这里是闭包的函数体
}

弱引用和无主引用

在闭包和捕获的实例总是互相引用并且总是同时销毁时,将闭包内的捕获定义为无主引用。
相反的,在被捕获的引用可能会变为nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil。这使我们可以在闭包体内检查它们是否存在。
注意:在被捕获的引用绝对不会变为nil用无主引用而不是弱引用

二、可选链

可选链式调用是在当前值可能为nil的可选值上请求和调用可选值的属性,下标和方法的方法。当可选值为nil的时候,调用返回nil。多个调用可以连在一起形成调用链,当其中某一个调用返回nil,那么整个调用链也会返回nil。

1.使用可选链式调用代替强制展开
可选链式调用返回结果和它原本的返回结果类型相同,但是变成了可选类型。

三、类型转换

swift中用isas操作实现类型转换。

1.检查类型
用类型检查操作符 is来检查一个实例是否属于特定子类型,返回true或false。

var movieCount = 0
var songCount = 0

for item in library {
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}

print("Media library contains \(movieCount) movies and \(songCount) songs")
// 打印 “Media library contains 2 movies and 3 songs”

2.向下转型
某类型的常量或者变量可能在幕后属于一个子类,当你确定它的类型时,你可以向下转到它的子类型,用as!或者` as? 转换。

类型转化会返回一个可选类型,当确定类型的时候才使用as!

3.Any和AnyObject的类型转换
Any可以表示任何类型,包括函数类型。
AnyObject可以表示任何类类型的实例。

只有你确定他们的行为和功能的时候才使用Any和AnyObject,在代码里使用确定的类型总是最好的。

四、扩展

扩展就是为一个已有的类、结构体、枚举类型或者协议类型添加新功能。这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。扩展和 Objective-C 中的分类类似。(与 Objective-C 不同的是,Swift 的扩展没有名字。)
swift中的扩展可以:
添加计算型属性和计算型类型属性
定义实例方法和类方法
提供新的构造器
定义下标
定义和使用新的嵌套类型
使一个已有类型符合某个协议

在 Swift 中,你甚至可以对协议进行扩展,提供协议要求的实现,或者添加额外的功能,从而可以让符合协议的类型拥有这些功能。

注意:扩展可以为一个类添加新的功能,但是不能重写已有的功能。
注意:如果你通过扩展为一个已有类型添加新功能,那么新功能对该类型的所有已有实例都是可用的,即使它们是在这个扩展定义之前创建的。
注意:扩展可以添加新的计算型属性,但是不可以添加存储型属性,也不可以为已有属性添加属性观察器。

上一篇下一篇

猜你喜欢

热点阅读