Τι είναι το κλείσιμο;
sobes.tech AI
Απάντηση από AI
Το κλείσιμο (closure) στη Swift είναι ένα αυτόνομο μπλοκ λειτουργικότητας ({}), το οποίο μπορεί να μεταβιβαστεί και να χρησιμοποιηθεί στον κώδικα. Τα κλεισίματα μπορούν να αιχμαλωτίζουν και να αποθηκεύουν αναφορές σε οποιεσδήποτε σταθερές και μεταβλητές από το πλαίσιο στο οποίο ορίζονται.
Παραδείγματα χρήσης:
- Ως επιχειρήματα συναρτήσεων (π.χ., χειριστές ολοκλήρωσης).
- Για τον ορισμό συμπεριφοράς κατά την επεξεργασία συλλογών (π.χ., χρησιμοποιώντας τις μεθόδους
map,filter,reduce,sorted). - Για την καθυστερημένη εκτέλεση κώδικα.
Σύνταξη:
// Βασική σύνταξη
{ (παραμέτροι) -> τύποςΕπιστροφής in
δηλώσεις
}
// Παράδειγμα κλεισίματος που δέχεται ένα Int και επιστρέφει ένα String
let integerToString: (Int) -> String = { (number: Int) -> String in
return "Αριθμός: \(number)"
}
Χαρακτηριστικά:
- Αυτόματη αιχμαλωσία μεταβλητών.
- Δυνατότητα ορισμού κλεισιμάτων χωρίς να καθορίζονται ρητά οι τύποι των παραμέτρων και η τιμή επιστροφής (σάκχαρο σύνταξης).
- Χρήση συντομευμένων ονομάτων για τις παραμέτρους ($0, $1, κ.λπ.).
- Σύνταξη κλεισίματος με trailing closure.
Αιχμαλωσία μεταβλητών:
Ένα κλείσιμο μπορεί να αιχμαλωτίσει μεταβλητές από το περιβάλλον του. Από προεπιλογή, η αιχμαλωσία γίνεται μέσω αναφοράς. Αν ένα κλείσιμο χρησιμοποιηθεί μετά την έξοδο της αρχικής μεταβλητής από το πεδίο ορατότητας, διατηρεί ακόμα πρόσβαση σε αυτή.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0 // Μεταβλητή από το εξωτερικό πλαίσιο
let incrementer: () -> Int = { // Κλείσιμο
runningTotal += amount // Αιχμαλωτίζει το runningTotal και το amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // Έξοδος: 10
print(incrementByTen()) // Έξοδος: 20
Λίστες αιχμαλωσίας (Capture Lists):
Χρησιμοποιούνται για να δηλώσουν ρητά πώς πρέπει να αιχμαλωτίζονται οι μεταβλητές - με τιμή ή με αναφορά, και επίσης για την αποφυγή ισχυρών κύκλων αναφορών (retain cycles).
class MyClass {
var value = 0
lazy var myClosure: () -> Void = { [self, value] in // Αιχμαλωτίζει το self μέσω αναφοράς, το value μέσω τιμής
print("Τιμή του self.value: \(self.value)")
print("Αιχμαλωτισμένη τιμή: \(value)")
}
deinit {
print("Η κλάση MyClass απελευθερώθηκε")
}
}
Για την αποφυγή ισχυρών κύκλων αναφορών κατά την αιχμαλωσία αντικειμένων κλάσεων, χρησιμοποιείται η σύνταξη [weak self] ή [unowned self].
class ViewController {
var dataFetcher: DataFetcher?
func fetchData() {
dataFetcher?.fetch { [weak self] result in // Αδύναμη αναφορά σε self
guard let self = self else { return } // Έλεγχος ύπαρξης του self
// Επεξεργασία αποτελέσματος
}
}
}
class DataFetcher {
var completionHandler: ((Result<String, Error>) -> Void)?
func fetch(completion: @escaping (Result<String, Error>) -> Void) {
self.completionHandler = completion
// Ασύγχρονη λειτουργία...
}
}