Swift中closure的循环引用记录

777 阅读1分钟

1、定义一个controller: TestController并添加如下代码

class TestController: UIViewController {
    
    typealias TestClosure = () -> ()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
    }

    deinit {
        print(self, #function)
    }
    
    // MARK: - private property
    private var name: String = "sdf"
    private var closure: TestClosure?
}


#### 然后添加方法进行测试:
  • 1
func test() {
        
        let closure: TestClosure = {
            self.name = ""
        }
        
        closure()
    }

不会循环引用

 closure引用了name,但是 self 没有引用closure,
 不构成互相强引用的关系

- ##### 2 ``` func test2() {
    let closure: TestClosure = {
        self.name = ""
    }
    
    closure()
    self.closure = closure
}
> **会**

closure引用了name,self 也引用closure, 构成互相强引用的关系


<br>
- ##### 3
func test3() {
    
    let closure: TestClosure = {[weak self] in
        
        let closure1: TestClosure = {
            self?.name = "dddd"
        }
        closure1()
    }
    
    closure()
    self.closure = closure
}

> 不会

closure中使用了[weak self] 修饰,所以在整个closure中的self都是弱引用, 虽然在closure1中并没有用[weak self]关键字,但是他此时调用的self是closure中的弱引用self 所以没有构成循环引用


<br>
- ##### 4
func test4() {
    
    let closure: TestClosure = {
        
        let closure1: TestClosure = { [weak self] in
            self?.name = "dddd"
        }
        closure1()
    }
    
    closure()
    self.closure = closure
}
> 会

closure中并没有使用了[weak self] 修饰,所以在整个closure中的self都是强引用, 虽然在closure1中并有用[weak self]关键字,但是他此时调用的self是closure中的强引用self 所以有构成循环引用


<br>
####结论:
如果在`closure`引用了`self.`但是`self`不引用`closure`,此时不会发生循环引用
如果`self`还引用了`closure`,这个时候就需要`[weak self]` 或者 `[unowned self]` 去修饰
如果有多层的`closure`嵌套,要在最外层的`closure`中修饰`self`,否则会发生循环引用