Swift委托协议无法阻止保留周期问题

时间:2015-12-28 12:34:59

标签: swift delegates swift2 protocols

在Swift中,如果我创建一个委托协议,它可以通过类和结构符合。

protocol MyDelegate {
  // Can be conformed to by class or struct
}

当我宣布代表时,问题出现了。如果委托是一个类实例,我希望变量是弱的,以避免保留循环。如果它是一个结构,就没有这样的需求 - 实际上,Swift不允许我让委托变量变弱。注意:我知道如何创建一个弱委托,但关键问题是 - 如果你创建一个可能很弱的委托协议,除非你只使它符合类,否则你不能强制执行保留周期。

class MyClass {
  // Want weak var here to avoid cyclical reference
  // but Swift won't allow it because MyDelegate can be
  // conformed by struct as well.  Dropping weak means
  // cyclical reference cannot be prevented
  weak var delegate: MyDelegate?
}

class MyConformingClass: MyDelegate {

}

or

struct MyConformingStruct: MyDelegate {

}

似乎我们需要始终将协议声明为类,因为非常规委托协议无法阻止保留周期:

protocol MyDelegate: class {

}

Swift允许你以这种方式射击自己的事实似乎违背了其安全设计理念。

2 个答案:

答案 0 :(得分:0)

保留周期需要两个......

如果你真的想这样做,那么为什么不省略weak并让它成为一个强有力的参考。如果委托还保持对其委派的对象的强引用,则只会出现问题。

因此,委托人有责任确保任何互惠引用都是弱的,这应该是MyClass是一个类的所有时间,因此你总是可以声明对它的弱引用。

答案 1 :(得分:0)

如果您确实希望在类或结构上支持协议,则可以始终将委托存储在单独的基础变量中。这样,当委托是一个类时,你可以有一个弱点。沿着以下几点:

协议MyDelegate {       //可以通过类或结构符合     }

class MyClass {
    private weak var delegateFromClass: AnyObject?
    private var delegateFromStruct: MyDelegate?
    var delegate: MyDelegate? {
        get {
            return (delegateFromClass as? MyDelegate) ?? delegateFromStruct
        }
        set {
            if newValue is AnyObject {
                delegateFromClass = newValue as? AnyObject
                delegateFromStruct = nil
            } else {
                delegateFromClass = nil
                delegateFromStruct = newValue
            }
        }
    }
}

class MyConformingClass: MyDelegate {

}

struct MyConformingStruct: MyDelegate {

}

print(" \(MyConformingClass() is AnyObject) \(MyConformingStruct() is AnyObject)")