swift备忘录之arc

swift中的arc与oc中很相似。需要注意的是swift中arc处理循环引用的关键字及其使用方式与oc中有所区分。循环引用在oc中,主要使用关键字weak或者unsafe_unretained来处理。在swift中使用weak和unowned来处理。

weak和unowned都表示不持有对象,区别在于,weak修饰的是optional的值,unowned修饰的是一定存在的值。也就是说weak修饰的var在运行时可以为nil,而unowned修饰的不可以。如果一个值使用unowned修饰,由于unowned修饰的值会自动解包,所以使用的时候,就不用加!符号了。

class instance中的使用例子

class Country {
    let name: String
    var capitalCity: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }
}
 
class City {
    let name: String
    unowned let country: Country
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}

摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks. 

Country和City类互相持有对方,如果不加unowned关键字,就会形成循环引用。如果City规定country属性不是必须有,则修饰的关键字可以改成weak,但是同时let也必须改成var,因为在运行时country可能有值,也可能为nil。

closure中的使用例子

如果closure赋值给一个var,然后在closure中又使用了类中的property等,那么会造成循环引用。例如:

class HTMLElement {
    
    let name: String
    let text: String?
    
    lazy var asHTML: () -> String = {
        if let text = self.text {
            return "<\(self.name)>\(text)"
        } else {
            return "<\(self.name) />"
        }
    }
    
    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
    
}

//使用
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// Prints "

hello, world

摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks.

其内存引用关系为:

swift备忘录之arc_第1张图片
closureRecycle.png

破除这么循环引用的方式是添加capture list。如下所示:

lazy var someClosure: (Int, String) -> String = {
    [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
    // closure body goes here
}

摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks. 

这个capture list放在closure的参数和返回值之前。

如果closure没有参数和返回值,那么需要这样写:

lazy var someClosure: () -> String = {
    [unowned self, weak delegate = self.delegate!] in
    // closure body goes here
}

摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks. 

通过in关键字将capture list和其他部分隔离开。上面这个例子中,改成如下方式就可以解除循环引用:

class HTMLElement {
    
    let name: String
    let text: String?
    
    lazy var asHTML: () -> String = {
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)"
        } else {
            return "<\(self.name) />"
        }
    }
    
    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
    
}

摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks. 

参考

《The Swift Programming Language》

你可能感兴趣的:(swift备忘录之arc)