Swift基础 循环引用导致内存泄漏

实例对象之间循环强引用

ARC并不是绝对安全的,当两个实例对象间相互强引用,就会造成引用循环,导致所占用的内存无法释放。

class Person{
    
    
    var name : String
    init(personName: String) {
    
    
        name = personName
    }
}

class Student: Person {
    
    
    var classmate : Student?
    override init(personName: String) {
    
    
        super.init(personName: personName)
    }
    deinit {
    
    
        //如果对象被正常释放会调用该方法
        print("\(self.name)被正常释放")
    }
}

class ViewController: UIViewController {
    
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        
        let xiaoHong = Student.init(personName: "xiaoHong")
        let xiaoMing = Student.init(personName: "xiaoMing")
        //彼此间相互都是对方的同学,造成相互强引用循环
        xiaoHong.classmate = xiaoMing
        xiaoMing.classmate = xiaoHong
        
        //程序执行到尾部,应该会对该区域内的局部变量进行释放。
    }
}

运行起来后,我们可以发现,程序并没有对xiaoHong与xiaoMing两个局部变量进行释放,所以没有打印deinit()方法内的语句。

弱引用解决强引用循环问题

class ViewController: UIViewController {
    
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        
        weak var xiaoHong = Student.init(personName: "xiaoHong")
        weak var xiaoMing = Student.init(personName: "xiaoMing")
        //彼此间相互都是对方的同学,造成相互强引用循环
        xiaoHong?.classmate = xiaoMing
        xiaoMing?.classmate = xiaoHong
        
        //程序执行到尾部,应该会对该区域内的局部变量进行释放。
    }
}

在创建实例的时候,将对象声明为弱引用对象就可以防止相互强引用的情况。
当然只声明其中一个为弱引用也是可以的,反正没有造成强引用循环就行。

var xiaoHong = Student.init(personName: "xiaoHong")
weak var xiaoMing = Student.init(personName: "xiaoMing")
//彼此间相互都是对方的同学,造成相互强引用循环
xiaoHong.classmate = xiaoMing
xiaoMing?.classmate = xiaoHong

无主引用解决强引用问题

和弱引用不同的是,无主引用通常都有一个值,因此,无主引用并不可以定义为可选类型。在声明前加关键字unowned可声明为无主引用类型。

class Student: Person {
    
    
    unowned var classmate : Student?
    override init(personName: String) {
    
    
        super.init(personName: personName)
    }
    deinit {
    
    
        //如果对象被正常释放会调用该方法
        print("\(self.name)被正常释放")
    }
}

class ViewController: UIViewController {
    
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        
        let xiaoHong = Student.init(personName: "xiaoHong")
        let xiaoMing = Student.init(personName: "xiaoMing")
        //彼此间相互都是对方的同学,造成相互强引用循环
        xiaoHong.classmate = xiaoMing
        xiaoMing.classmate = xiaoHong
        
        //程序执行到尾部,应该会对该区域内的局部变量进行释放。
    }
}

运行结果:

xiaoMing被正常释放
xiaoHong被正常释放

猜你喜欢

转载自blog.csdn.net/kkkenty/article/details/124785534
今日推荐