美文网首页
swift备忘录之arc

swift备忘录之arc

作者: byn | 来源:发表于2017-02-10 12:05 被阅读16次

    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)</\(self.name)>"
            } 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 "<p>hello, world</p>
    
    摘录来自: Apple Inc. “The Swift Programming Language (Swift 3)”。 iBooks. 
    

    其内存引用关系为:

    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)</\(self.name)>"
            } 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

          本文链接:https://www.haomeiwen.com/subject/uqjgittx.html