В частности, как работает управление памятью Swift с опциями с использованием шаблона делегата?Как работает управление памятью Swift?
Будучи привыкшим к написанию шаблона делегата в Objective-C, мой инстинкт состоит в том, чтобы сделать делегата weak
. Например, в Objective-C:
@property (weak) id<FooDelegate> delegate;
Однако выполнение этого в Swift не так прямолинейно.
Если у нас есть только обычный выглядящий протокол:
protocol FooDelegate {
func doStuff()
}
Мы не можем объявлять переменные этого типа, как слабая:
weak var delegate: FooDelegate?
Выдает ошибку:
'weak' cannot be applied to non-class type 'FooDelegate'
Таким образом, мы либо не используйте ключевое слово weak
, что позволяет нам использовать structs
и enums
в качестве делегатов, или мы изменим наш протокол к следующему:
protocol FooDelegate: class {
func doStuff()
}
что позволяет использовать weak
, но не позволяет нам использовать structs
или enums
.
Если я не делаю свой протокол протоколом класса и поэтому не использую weak
для моей переменной, я создаю цикл сохранения, правильно?
Существует ли какая-либо мыслимая причина, почему любой протокол, предназначенный для использования в качестве протокола делегата, не должен быть протоколом класса, так что переменные этого типа могут быть weak
?
я в первую очередь спрашиваю, потому что в разделе делегации the Apple official documentation on Swift protocols, они представляют собой пример протокола неклассового и без слабого переменного, используемого в качестве делегата в свой класс:
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 думает, что мы должны использовать структуры как делегаты? Или это просто плохой пример, и реалистично, протоколы делегатов должны быть объявлены как протоколы только для классов, чтобы делегированный объект мог иметь слабую ссылку на его делегата?
«Если я не сделаю протокол протоколом класса и поэтому не использую слабый для моей переменной, я создаю цикл сохранения, правильно?» Нет, не правильно. Если делегат не сохранит ссылку на своего хозяина. В примере Swift этого не происходит. DiceGameDelegate имеет параметры DiceGame в своих функциях, но у него нет DiceGame _property_, что вызовет постоянную ссылку на его хост. – matt
Но в большинстве случаев фактического использования делегат имеет ссылку на делегированный объект. – nhgrif
Правильно, и это именно то, о чем говорит мой ответ. - В основном вы спросили, что особенного в этом примере Apple, который использует _not_ класс и слабый делегат, и я сказал вам. – matt