MST
星途 面试题库

面试题:Swift中如何确保闭包不会引发安全漏洞

闭包在Swift编程中广泛使用,但如果使用不当可能会导致内存泄漏或其他安全问题。请详细说明Swift中闭包可能引发安全漏洞的场景,例如强引用循环等,并阐述如何通过`weak`、`unowned`关键字以及正确的闭包定义和使用方式来避免这些安全隐患。
22.4万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试

Swift中闭包可能引发安全漏洞的场景

  1. 强引用循环:当闭包捕获了一个对象,而这个对象又持有对闭包的引用时,就会形成强引用循环。例如:
class ViewController: UIViewController {
    var completionHandler: (() -> Void)?
    override func viewDidLoad() {
        super.viewDidLoad()
        completionHandler = { [unowned self] in
            self.doSomething()
        }
        // 假设这里调用了completionHandler
        completionHandler?()
    }
    func doSomething() {
        print("Doing something")
    }
}

在上述代码中,如果没有[unowned self]捕获列表,completionHandler闭包会捕获self,而self又持有completionHandler,从而导致强引用循环。

避免安全隐患的方式

  1. 使用weak关键字
    • weak用于创建弱引用,被弱引用的对象不会增加引用计数。当对象被释放时,所有指向它的弱引用会自动被设置为nil
    • 示例:
class SomeClass {
    var closure: (() -> Void)?
    init() {
        let weakSelf = weak self
        closure = {
            if let strongSelf = weakSelf {
                strongSelf.doSomething()
            }
        }
    }
    func doSomething() {
        print("Do something in SomeClass")
    }
}
  1. 使用unowned关键字
    • unowned创建非拥有引用,和weak不同,unowned引用不会自动设置为nil,因此确保被引用的对象在闭包执行期间一直存在非常重要。
    • 适合场景:当你确定被引用的对象不会比闭包先释放时使用。如上述ViewController示例中,在viewDidLoad方法中self在闭包执行期间肯定存在,所以可以使用unowned
  2. 正确的闭包定义和使用方式
    • 明确捕获列表:在定义闭包时,明确写出捕获列表,避免隐式捕获导致意外的强引用循环。
    • 适时释放闭包引用:如果闭包不再需要使用,及时将其设置为nil,打破可能存在的强引用循环。例如,在ViewController类中,如果completionHandler不再使用,可以在合适的生命周期方法(如deinit)中将其设置为nil