Memory management is a problem that can’t be ignored in development, and circular references are the most common problem that causes memory leaks. Let’s look at a few simple problems and how to solve them:

A circular reference

var name:String?
var myClosure : (() -> Void)?
override func viewDidLoad(a) {
    super.viewDidLoad()
    
    myClosure = {
        self.name = "Little Horse drop"
    }
    myClosure!()
}  
Copy the code

We then use the destructor to check for circular references

deinit {
    print("deinit")}Copy the code

The above function call, when leaving the page, does not deinit, self holds myClosure, and myClosure holds self, obviously creating a circular reference. So how do we break this holding pattern?

Method one: Use a master referenceunowned

myClosure = {[unowned self] in
    self.name = "Little Horse drop"} myClosure! (a)Copy the code

Method two: Use weak referencesweak

myClosure = {[weak self] in
    self? .name ="Little Horse drop"} myClosure! (a)Copy the code

So what’s the difference between an unmanned reference unowned and a weak reference weak? So let’s put a delay in there and see.

myClosure = {[unowned self] in
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        self.name = "Little Horse drop"
        print(self.name ?? "") } } myClosure! (a)Copy the code

Error: Runtime (CHS) -chs (x86) -chs (x86) -chs (x86) -chs (x86) -chs (x86) -chs (x86) -chs (X86) -chs (X86) -chs (X86) -Chs (X86) -Chs (X86)

myClosure = {[weak self] in
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        self? .name ="Little Horse drop"
        print(self? .nameas Any) } } myClosure! (a)Copy the code

It prints nil. Why is that? Because the unowned unmaster reference destroys both, whereas weak sets to nil when self destroys. So how do we solve this problem? Extend the life cycle of Self in the same way as weakSelf and strongSelf in OC.

Extended life cycle (Guard)

myClosure = {[weak self] in
    guard let self = self else { return }
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        self.name = "Little Horse drop"
        print(self.name!) } } myClosure! (a)Copy the code

Because self has been removed from the keyword, using self is the same as using strongSelf.

Circular reference in RXSwift

Since closures are so easy to cause circular references, and subscriptions use a lot of closures to create sequences in RXSwift, what causes circular references?

Case 1:

self.pwdTF.rx.text.orEmpty.skip(1)
        .bind(to: self.rx.title)
        .disposed(by: disposeBag)
Copy the code

Text binding self.rx.title does not cause a circular reference because self.rx.title, as an argument, does not cause a circular reference.

Situation 2:

self.observable = Observable<Any>.create({ (anyObserver) -> Disposable in
    anyObserver.onNext("Little Horse drop")
    print(self)
    return Disposables.create()
})
Copy the code

Create sequence closures using self, self -> Observable -> create{} -> self to form circular references

self.observable? .subscribe(onNext: { (argue)in
        print(self)
        }).disposed(by: disposeBag)
Copy the code

A subscription closure uses self, self -> Observable -> subscribe{} -> self to form a circular reference.

Case 3:

    Observable<Any>.create { (anyObserver) -> Disposable in
        self.observer = anyObserver
        anyObserver.onNext("Little Horse drop")  
        print(self)// A temporary variable that does not generate a circular reference
        return Disposables.create()
        }.subscribe(onNext: { (item) in
            print(item)
            print(self)// Circular reference
        }).disposed(by: disposeBag)
}
Copy the code

Create sequence closure anyObserver is a temporary variable assigned to self that does not generate circular references, In the subscription closure :self -> bag -> sink -> AnonymousObserver -> _eventHandler, so if self is used in the subscription, be careful.

Solution: Break circular references in RXSwift. There are many other ways to do this, not just using Weak

Solution:

For example, rational use. Completed or. Error manually dispose() to use.Copy the code