Sobes.tech
Middle

Εξηγήστε τη διαφορά μεταξύ closures escaping και non-escaping, και σε ποιες περιπτώσεις είναι απαραίτητο να χρησιμοποιήσετε το @escaping.

sobes.tech AI

Απάντηση από AI

Οι προεπιλεγμένες κλεισίματα είναι μη-escape.

Μη-escape κλείσιμο:

  • Εκτελείται στο σώμα της λειτουργίας στην οποία περνάει.
  • Συλλαμβάνει μεταβλητές, αλλά τις απελευθερώνει μετά την ολοκλήρωση της λειτουργίας.
  • Δεν επιβιώνει της λειτουργίας.
func doSomething(completion: () -> Void) {
    // Κλήση completion εδώ
    completion() 
}

Escape κλείσιμο:

  • Εκτελείται μετά την επιστροφή της λειτουργίας στην οποία περνάει.
  • Επιβιώνει του σώματος της λειτουργίας.
  • Μπορεί να αποθηκευτεί για μελλοντική εκτέλεση, π.χ., σε άλλο νήμα ή ασύγχρονα.
  • Συλλαμβάνει μεταβλητές, διατηρώντας ισχυρές αναφορές, που μπορεί να οδηγήσει σε κύκλους ισχυρών αναφορών (retain cycles). Απαιτεί ρητή δήλωση @escaping.
class DataManager {
    var completionHandlers: [() -> Void] = []

    func addCompletionHandler(handler: @escaping () -> Void) {
        completionHandlers.append(handler)
    }

    func performTasks() {
        // Εκτέλεση εργασιών...
        for handler in completionHandlers {
            handler() // Κλήση handlers αργότερα
        }
    }
}

Η χρήση του @escaping είναι απαραίτητη στις ακόλουθες περιπτώσεις:

  • Όταν η κλείσιμο αποθηκεύεται σε ιδιότητα μιας κλάσης ή δομής.
  • Όταν η κλείσιμο περνά σε άλλο νήμα ή ασύγχρονη λειτουργία (π.χ., αίτημα δικτύου, GCD, OperationQueue).
  • Όταν η κλείσιμο χρησιμοποιείται ως χειριστής συμβάντος ή delegate.