2016-09-15 22 views
32

Tôi mới sử dụng Swift và tôi đã đọc hướng dẫn khi tôi gặp phải các đóng cửa thoát. Tôi đã không nhận được mô tả của hướng dẫn sử dụng cả. Có thể ai đó xin vui lòng giải thích cho tôi những gì thoát đóng cửa là trong Swift trong điều kiện đơn giản.Thoát đóng cửa trong Swift

+3

Để báo giá từ hướng dẫn sử dụng, “Một đóng được cho là thoát khỏi một hàm khi đóng được chuyển như một đối số cho hàm, nhưng được gọi sau khi hàm trả về.” Vì vậy, nếu đóng cửa được gọi là đồng bộ, không thoát. Một ví dụ có thể là một kết thúc liệt kê hoặc các phương thức hàm 'map',' filter', etc. Nếu nó được gọi là không đồng bộ (tức là sau này), nó sẽ thoát. Ví dụ phổ biến nhất về thoát đóng sẽ là trình xử lý hoàn thành cho một số tác vụ không đồng bộ chậm, như yêu cầu mạng. – Rob

+0

Nếu bạn nghĩ câu trả lời của tôi trả lời câu hỏi của bạn, hãy xem xét chấp nhận bằng cách nhấp vào dấu kiểm đó. – Sweeper

Trả lời

61

xem xét lớp này:

class A { 
    var closure: (() -> Void)? 
    func someMethod(closure:() -> Void) { 
     self.closure = closure 
    } 
} 

someMethod gán việc đóng cửa thông qua tại, để sở hữu một trong lớp.

Bây giờ ở đây có một lớp:

class B { 
    var number = 0 
    var a: A = A() 
    func anotherMethod() { 
     a.someMethod { self.number = 10 } 
    } 
} 

Nếu tôi gọi anotherMethod, việc đóng cửa { self.number = 10 } sẽ được lưu trữ trong trường hợp của A. Kể từ khi self được chụp trong đóng cửa, trường hợp của A cũng sẽ giữ một tham chiếu mạnh mẽ với nó.

Về cơ bản đó là ví dụ về việc đóng cửa đã thoát!

Có thể bạn đang tự hỏi, "Cái gì? Vậy cái đóng cửa đã thoát ra từ đâu và đến?"

Việc đóng cửa thoát ra khỏi phạm vi của phương pháp, đến phạm vi của lớp học. Và nó có thể được gọi sau, ngay cả trên một sợi khác! Điều này có thể gây ra vấn đề nếu không được xử lý đúng cách.

Để tránh vô tình thoát đóng cửa và gây duy trì chu kỳ và các vấn đề khác, sử dụng @noescape thuộc tính:

class A { 
    var closure: (() -> Void)? 
    func someMethod(@noescape closure:() -> Void) { 
    } 
} 

Bây giờ nếu bạn cố gắng viết self.closure = closure, nó không biên dịch!

Cập nhật:

Trong Swift 3, tất cả thông số đóng không thể thoát theo mặc định. Bạn phải thêm thuộc tính @escaping để làm cho việc đóng có thể thoát khỏi phạm vi hiện tại. Điều này làm tăng thêm sự an toàn cho mã của bạn!

class A { 
    var closure: (() -> Void)? 
    func someMethod(closure: @escaping() -> Void) { 
    } 
} 
+0

Cảm ơn rất nhiều. Điều đó thực sự hữu ích. –

+0

Nếu bạn nghĩ câu trả lời của tôi trả lời câu hỏi của bạn, hãy xem xét chấp nhận câu hỏi bằng cách nhấp vào dấu kiểm đó @NikhilSridhar – Sweeper

+1

Khen ngợi câu trả lời này! Một lời giải thích trong thuật ngữ đơn giản, với một câu trả lời đơn giản. –

12

I find this website very helpful on that matter Giải thích đơn giản sẽ là:

Nếu đóng cửa được thông qua như là một cuộc tranh cãi với một chức năng và nó được gọi sau khi trở về chức năng, việc đóng cửa là thoát.

Đọc thêm tại liên kết Tôi đã vượt qua ở trên! :)

27

Tôi đang đi theo một cách đơn giản hơn.

Hãy xem xét ví dụ sau:

func testFunctionWithNonescapingClosure(closure:() -> Void) { 
     closure() 
} 

Trên đây là một tổ chức phi thoát đóng cửa vì việc đóng cửa là gọi trước khi trở về phương pháp.

xem xét ví dụ tương tự với một hoạt động asynchoronous:

func testFunctionWithEscapingClosure(closure:@escaping() -> Void) { 
     DispatchQueue.main.async { 
      closure() 
     } 
} 

Ví dụ trên có chứa một đóng cửa thoát vì gọi đóng cửa có thể xảy ra sau khi hàm trả về do hoạt động không đồng bộ.

var completionHandlers: [() -> Void] = [] 
func testFunctionWithEscapingClosure(closure: @escaping() -> Void) { 
     completionHandlers.append(closure) 
} 

Trong trường hợp trên, bạn có thể dễ dàng nhận ra việc đóng cửa đang chuyển động bên ngoài cơ quan chức năng nên nó cần phải được một đóng cửa trốn thoát.

Đóng và thoát không thoát được thêm vào để tối ưu hóa trình biên dịch trong Swift 3. Bạn có thể tìm kiếm lợi thế của việc đóng gói nonescaping.

+0

Sẽ tốt hơn nếu bạn thêm vào câu trả lời hay này những lợi thế của việc đóng cửa nonescaping và các ví dụ khi bạn có thể cần nó. –

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