在ARC中,对于一般的delegate,我们会在声明中将其指定为weak,在这个delegate实际的对象被释放的时候,会被重置回nil。这可以保证即使delegate已经不存在时,我们也不会由于访问已被回收的内存而导致崩溃。ARC的这个特性杜绝了Cocoa开发中一种非常常见的奔溃错误。 在Swift中我们也希望这么做,但是当我们尝试书写这样的代码的时候,编译器却不会让我们通过
protocol myClassDelegate {
func method()
}
class MyClass {
weak var delegate: myClassDelegate? //error: 'weak' may only be applied to class and class-bound protocol types,not'myClassDelegate'
}
class ViewController: UIViewController,myClassDelegate{
var someInstance: MyClass!
override func viewDidLoad() {
super.viewDidLoad()
someInstance = MyClass()
someInstance.delegate = self;
}
func method(){
print("Do something")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
这是因为Swift的protocol是可以被除了class以外的其他类型遵守的,而对于像struct或是enum这样的类型,本身就不通过引用计数来管理内存,所以也不可能用weak这样的ARC的概念来进行修饰。 想要在Swift中使用 weak delegate,我们需要将protocol限制在class内。一种做法是将protocol声明为OC的,这可以通过在protocol前面加上@objc 关键字来达到,OC中的protocol都只是类能实现,因此用weak来修饰就合理了:
@objc protocol myClassDelegate {
func method()
}
另外一种可能更好的办法是在protocol声明的名字后面加上class, 这可以为编译器显示地指明protocol只能由class来实现。
protocol myClassDelegate: class {
func method()
}
相比起添加@objc,第二种方法更能表现出问题的实质,同时也避免了过多的不必要的OC兼容,可以说是一种更好的解决方式。