具体来说,Swift内存管理如何使用委托模式与选项一起使用?
习惯于在Objective-C中编写委托模式,我的直觉是创建委托weak
.例如,在Objective-C中:
@property (weak) id delegate;
但是,在Swift中这样做并不是那么简单.
如果我们只有一个看似正常的协议:
protocol FooDelegate { func doStuff() }
我们不能将此类型的变量声明为弱:
weak var delegate: FooDelegate?
产生错误:
'weak'不能应用于非类型'FooDelegate'
所以我们要么不使用关键字weak
,这允许我们使用structs
和enums
作为代理,或者我们将协议更改为以下内容:
protocol FooDelegate: class { func doStuff() }
这允许我们使用weak
,但不允许我们使用structs
或enums
.
如果我不使我的协议成为类协议,因此不使用weak
我的变量,我正在创建一个保留周期,对吗?
是否有任何可以想象的原因,为什么任何打算用作委托协议的协议不应该是类协议,以便这种类型的变量可以weak
?
我主要问一下,因为在关于Swift协议的Apple官方文档的委托部分中,它们提供了一个非类协议和一个非弱变量的示例,用作其类的委托:
protocol DiceGameDelegate { func gameDidStart(game: DiceGame) func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) func gameDidEnd(game: DiceGame) }
class SnakesAndLadders: DiceGame { let finalSquare = 25 let dice = Dice(sides: 6, generator: LinearCongruentialGenerator()) var square = 0 var board: [Int] init() { board = [Int](count: finalSquare + 1, repeatedValue: 0) board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02 board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08 } var delegate: DiceGameDelegate? func play() { square = 0 delegate?.gameDidStart(self) gameLoop: while square != finalSquare { let diceRoll = dice.roll() delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll) switch square + diceRoll { case finalSquare: break gameLoop case let newSquare where newSquare > finalSquare: continue gameLoop default: square += diceRoll square += board[square] } } delegate?.gameDidEnd(self) } }
我们是否应该将此视为Apple认为我们应该使用结构作为代表的暗示?或者这只是一个不好的例子,并且实际上,委托协议应该被声明为仅类协议,以便委托对象可以保存对其委托的弱引用?
我们是否应该将此视为Apple认为我们应该使用结构作为代表的暗示?或者这只是一个不好的例子,并且实际上,委托协议应该被声明为仅类协议,以便委托对象可以保存对其委托的弱引用?
这就是事情.在现实生活Cocoa编程中,代表可能是现有的类.它是一个类,因为它存在于某个其他目的,只有一个类可以满足 - 因为Cocoa需要它.
例如,通常,以iOS为例,一个视图控制器需要充当另一个视图控制器的委托,以便在它们之间来回布置消息.视图控制器的所有权由视图控制器层次结构决定,而不是由其他任何东西决定.所以,在Swift中,就像在Objective-C中一样,你最好制作那个delegate
属性weak
,因为如果一个视图控制器突然占用了另一个视图控制器的内存管理权限,这将是非常糟糕的!
因此,在Cocoa框架的现实世界中,存在不正确的所有权或保留周期的严重危险.这就是weak
解决的问题.但正如你正确地说,它只适用于课程.
然而,书中的例子是关于生活在一个抽象的人造Swift-only世界中的一些物体.在那个世界中,只要你没有循环的危险(保留周期),就没有理由不使用结构,也没有理由担心内存管理.但是这个世界并不是你通常会编程的世界!而且这个世界不是你的Objective-C委托模式来自和属于的框架Cocoa世界.