2016-09-13 15 views
6

Tôi có một ví dụ:Capture danh sách trong Swift

class Animal { 
    var stamina = 0 

    func increaseStamina() { 
     stamina += 1 
    } 
} 

var a = Animal() 

var closure = { [weak a] in 
    a?.stamina = 10 
} 

a.stamina // 0 
a.increaseStamina() 
a.stamina // 1 
closure() 
a.stamina // 10 

nếu tôi thay đổi closure như thế này:

var closure = { [weak a] in 
    a = Animal() 
    a?.stamina = 10 
} 

sau đó nó in một cái gì đó như thế này:

a.stamina // 0 
a.increaseStamina() 
a.stamina // 1 
closure() 
a.stamina // 1 

Tại sao dòng cuối cùng khác nhau?

+0

Bản sao có thể có của [Làm cách nào để đóng các giá trị từ các cuộc gọi trước?] (Http://stackoverflow.com/questions/37839020/how-do-closures-capture-values-from-previous-calls) – Honey

+1

@Honey: Tôi không chắc liệu điều đó có đủ điều kiện như một bản sao hay không. Nó có liên quan, nhưng không có danh sách chụp trong câu hỏi đó, và không có lớp học (loại tham chiếu). –

+0

@MartinR Ohhhhk – Honey

Trả lời

5

Tất cả các mục nhập trong danh sách chụp tạo ra một biến số địa phương trong trường hợp đóng cửa . Nó được khởi tạo với giá trị của biến số có cùng tên trong ngữ cảnh bên ngoài, nhưng có thể được sửa đổi một cách độc lập.

Trong trường hợp của bạn

var closure = { [weak a] in 
    a = Animal() 
    a?.stamina = 10 
} 

a bên trong đóng cửa được khởi tạo với một tham chiếu yếu đến đối tượng Animal tạo trước đó, nhưng nó không phụ thuộc vào bên ngoài a biến. a = Animal() tạo một phiên bản mới và gán tham chiếu cho biến cục bộ đó a. Bởi vì nó là một tham chiếu yếu, đối tượng được deallocated ngay lập tức (bạn có thể xác minh rằng bằng cách thêm print(a) trong đóng cửa). Biến ngoài a vẫn tham chiếu đối tượng ban đầu:

print(a.stamina) // 0 
a.increaseStamina() 
print(a.stamina) // 1 
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100a03060) 
closure() 
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100a03060) 
print(a.stamina) // 1 

Nếu bạn bỏ qua danh sách chụp sau đó a bên trong đóng cửa và ngoài việc đóng cửa tham khảo các biến tương tự, và một trường hợp mới có thể được gán bên trong đóng cửa:

var a = Animal() 

var closure = { 
    a = Animal() 
    a.stamina = 10 
} 

print(a.stamina) // 0 
a.increaseStamina() 
print(a.stamina) // 1 
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100b06ac0) 
closure() 
print(ObjectIdentifier(a)) // ObjectIdentifier(0x0000000100e00070) 
print(a.stamina) // 10 

để biết thêm thông tin và chi tiết, xem "Capture Lists" trong tài liệu tham khảo Swift (nhờ vậy @Arthur cho việc cung cấp liên kết).

+2

Vì tôi cũng tò mò, [đây là phần liên quan trong tài liệu tham khảo Swift của Apple (Swift 2.2)] (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions .html # // apple_ref/doc/uid/TP40014097-CH32-ID544): "Đối với mỗi mục nhập trong danh sách chụp, hằng số được khởi tạo thành giá trị * của hằng số hoặc biến có cùng tên trong phạm vi xung quanh [...] " – Arthur

+0

@Arthur: Cảm ơn! - Tôi tự hỏi tại sao tài liệu lại nói * "... một hằng số được khởi tạo ..." *. Trong trường hợp này của tham chiếu bị bắt yếu, 'a' là một biến * * trong phần đóng. –

+0

Hi @MartinR, tại sao 'var closure = {[weak a] trong a? .amamina = 10 }' cho tôi 'a.stamina' // 10, bởi vì bạn nói' a' trong đóng là phụ thuộc từ ' a' bên ngoài đóng cửa. – Khuong

Các vấn đề liên quan