美文网首页
swift防止循环引用简单整理

swift防止循环引用简单整理

作者: 悃破 | 来源:发表于2017-10-23 10:39 被阅读107次

weak

弱引用不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。ARC 会在引用的实例被销毁后自动将其赋值为nil。并且因为弱引用可以允许它们的值在运行时被赋值为nil,所以它们会被定义为可选类型变量,而不是常量。

unowned

和弱引用类似,无主引用不会牢牢保持住引用的实例。和弱引用不同的是,无主引用在其他实例有相同或者更长的生命周期时使用。无主引用通常都被期望拥有值。不过 ARC 无法在实例被销毁后将无主引用设为nil,因为非可选类型的变量不允许被赋值为nil。

代理的循环引用

使用weak标记
如下定义两个协议

protocol TestProtocol: class  {    
    func testProtocolFunc()
}

@objc protocol TestProtocol2 {
    func testProtocolFunc2()
}

⚠️注意:在使用weak标记时delegate时,协议需要继承class或用@objc标记,否则会爆错。'weak' may only be applied to class and class-bound protocol types, not 'TestProtocol'
使用协议时:

class TestClass {
    weak var delegate: TestProtocol?
    weak var delegate2: TestProtocol2?
    func test() {
        self.delegate?.testProtocolFunc()
        self.delegate2?.testProtocolFunc2()
    }
}

闭包的防止循环引用

闭包防止循环引用时使用weak unowned的原则:
a、在闭包和捕获的实例总是互相引用并且总是同时销毁时,将闭包内的捕获定义为无主引用。
b、相反的,在被捕获的引用可能会变为nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil。这使我们可以在闭包体内检查它们是否存在。
c、如果被捕获的引用绝对不会变为nil,应该用无主引用,而不是弱引用。
如(a、b暂未遇到合适的例子):

class SwiftViewController: UIViewController {

    var swiftBlock: ((String) -> Void)?
    var name = ""
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.swiftBlock = { [unowned self] str in
            print("\(self.title ?? "没有标题")")
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        if let block = self.swiftBlock {
            block("测试swiftblock")
        }
    }

    deinit {
        print("SwiftViewController销毁了")
    }

}

类的循环引用

使用weak例,定义了两个类:Person和Apartment,用来建模公寓和它其中的居民。Apartment的tenant属性被声明为弱引用以防止循环引用。

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { print("\(name) is being deinitialized") }
}

class Apartment {
    let unit: String
    init(unit: String) { self.unit = unit }
    weak var tenant: Person?
    deinit { print("Apartment \(unit) is being deinitialized") }
}

建立两个变量(john和unit4A)之间的强引用,并关联两个实例

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

使用unowned例,定义了两个类,Customer和CreditCard,模拟了银行客户和客户的信用卡。这两个类中,每一个都将另外一个类的实例作为自身的属性。这种关系可能会造成循环强引用。一个客户可能有或者没有信用卡,但是一张信用卡总是关联着一个客户,因此将customer属性定义为无主引用,用以避免循环强引用。

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { print("\(name) is being deinitialized") }
}
class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}

建立两个变量(john和card)之间的强引用,并关联两个实例

var john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

(如有错误欢迎斧正)
参考:
极客学院自动引用计数
swift中的delegate

相关文章

  • swift防止循环引用简单整理

    weak 弱引用不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强...

  • iOS swift 防止循环引用

    yourFunc就是你自己写的需要回调作为参数的函数arg 为参数上面这块代码可以避免循环引用第一次在简书写点东西...

  • Swift如何正确防止循环引用

    循环引用就是两个对象互相强引用对方,导致对象实例无法释放,那么在swift中如何防止这种循环引用呢? 一种方式是使...

  • Swift--内存管理

    Swift内存管理概述 强引用循环 打破强引用循环 闭包中的强引用循环 Swift内存管理概述 Swift中的AR...

  • 【Swift】block防止self循环引用

    方法1、 weak var weakSelf =self self.block ={() -> () in...

  • swift-07 闭包

    输出结果 定义弱引用 防止循环引用

  • 防止循环引用

  • 平常开发中会遇到的内存泄漏

    一、Block循环引用 防止block循环引用的方法:(弱引用) __weaktypeof(self) weaks...

  • StrongSelf

    weakSelf : 防止循环引用 strongSelf: 防止释放 需要 强引用weakSelf,主要是处理一...

  • Swift weak delegate

    需要使用delgate时,为了防止循环引用需要添加weak关键字,但是上面的代码XCode会报错。因为swift里...

网友评论

      本文标题:swift防止循环引用简单整理

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