Cụ thể, cách quản lý bộ nhớ Swift hoạt động với các tùy chọn bằng cách sử dụng mẫu đại biểu?Quản lý bộ nhớ Swift hoạt động như thế nào?
Đã quen với việc viết mẫu đại biểu trong Mục tiêu-C, bản năng của tôi là làm cho đại biểu weak
. Ví dụ: trong Mục tiêu-C:
@property (weak) id<FooDelegate> delegate;
Tuy nhiên, thực hiện điều này trong Swift không quá thẳng thắn.
Nếu chúng ta có chỉ là một giao thức trai bình thường:
protocol FooDelegate {
func doStuff()
}
Chúng ta không thể khai báo các biến thuộc loại này như yếu:
weak var delegate: FooDelegate?
Tạo các lỗi:
'weak' cannot be applied to non-class type 'FooDelegate'
Vì vậy, chúng tôi hoặc không sử dụng từ khóa weak
, cho phép chúng tôi sử dụng structs
và enums
như các đại biểu, hoặc chúng ta thay đổi giao thức của chúng tôi như sau:
protocol FooDelegate: class {
func doStuff()
}
nào cho phép chúng ta sử dụng weak
, nhưng không cho phép chúng ta sử dụng structs
hoặc enums
.
Nếu tôi không thực hiện giao thức của mình một giao thức lớp, và do đó không sử dụng weak
cho biến của tôi, tôi đang tạo chu trình giữ lại, đúng không?
Có lý do nào có thể tưởng tượng được tại sao bất kỳ giao thức nào được sử dụng làm giao thức đại biểu không phải là giao thức lớp sao cho các biến thuộc loại này có thể là weak
?
tôi chủ yếu hỏi, bởi vì trong phần phái đoàn của the Apple official documentation on Swift protocols, họ cung cấp một ví dụ về một giao thức phi hạng nhất và một biến phi yếu được sử dụng như các đại biểu đến lớp học của họ:
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)
}
}
Chúng ta có nên coi đây là gợi ý cho rằng Apple cho rằng chúng ta nên sử dụng cấu trúc với tư cách là đại biểu không? Hay đây chỉ là một ví dụ xấu, và thực tế, các giao thức ủy nhiệm nên được khai báo như là các giao thức chỉ lớp để đối tượng được ủy quyền có thể chứa một tham chiếu yếu tới đại biểu của nó?
"Nếu tôi không làm giao thức của mình thành giao thức lớp và do đó không sử dụng yếu cho biến của tôi, tôi đang tạo chu trình giữ lại, đúng không?" Không, không đúng. Không, trừ khi các đại biểu giữ lại một tham chiếu đến máy chủ của nó. Trong ví dụ Swift, điều đó không xảy ra. DiceGameDelegate có các tham số DiceGame trong các hàm của nó, nhưng nó không có DiceGame _property_ mà có thể gây ra một tham chiếu liên tục đến máy chủ của nó. – matt
Nhưng trong hầu hết các trường hợp sử dụng thực tế, đại biểu có một tham chiếu đến đối tượng được ủy quyền. – nhgrif
Đúng, và đó chính xác là câu trả lời của tôi. - Bạn hỏi, về cơ bản, những gì đặc biệt về ví dụ này của Apple mà không _not_ sử dụng một lớp và một đại biểu yếu, và tôi đã nói với bạn. – matt