Sobes.tech
Junior

Mis on sulgemine?

sobes.tech AI

Vastus AI-lt

Sulgemine (closure) Swiftis on iseseisev funktsionaalsuse plokk ({}), mida saab koodis edasi anda ja kasutada. Sulgemised võivad haarata ja salvestada viiteid mis tahes konstantidele ja muutujatele kontekstist, kus need on määratletud.

Kasutamise näited:

  • Funktsioonide argumentidena (näiteks Completion Handlers).
  • Kolektsioonide käitumise määratlemiseks iteratsiooni ajal (näiteks kasutades meetodeid map, filter, reduce, sorted).
  • Koodi hilisemaks täitmiseks.

Süntaks:

// Põhisüntaks
{ (parameetrid) -> tagastatüüp in
    laused
}

// Näide sulgemisest, mis võtab vastu Int ja tagastab String
let integerToString: (Int) -> String = { (number: Int) -> String in
    return "Number: \(number)"
}

Omadused:

  • Muutujate automaatne haaramine (capturing values).
  • Võimalus määratleda sulgemisi ilma otsese parameetrite ja tagastatüüpide määramiseta (süntaktiline suhkur).
  • Lühendatud parameetrite nimede kasutamine ($0, $1 jne).
  • Sulgemise süntaks (trailing closure syntax).

Muutujate haaramine:

Sulgemine võib haarata oma keskkonnast muutujad. Vaikimisi toimub haaramine viitega. Kui sulgemist kasutatakse pärast seda, kui algne muutuja on välja läinud, säilitab sulgemine endiselt juurdepääsu sellele.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0 // Väline muutuja
    let incrementer: () -> Int = { // Sulgemine
        runningTotal += amount // Haarab runningTotal ja amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // Väljund: 10
print(incrementByTen()) // Väljund: 20

Haaramise nimekirjad (Capture Lists):

Need võimaldavad selgelt määrata, kuidas muutujad haaratakse - väärtusena või viitega, ning vältida tugevaid viite tsükleid (retain cycles).

class MyClass {
    var value = 0

    lazy var myClosure: () -> Void = { [self, value] in // Haarab self viitega, value väärtusega
        print("self.value väärtus: \(self.value)")
        print("Haaratud väärtus: \(value)")
    }

    deinit {
        print("MyClass eksemplar vabastatud")
    }
}

Tugevate viite tsüklite vältimiseks haarates objekte klassidest, kasutatakse süntaksit [weak self] või [unowned self]:

class ViewController {
    var dataFetcher: DataFetcher?

    func fetchData() {
        dataFetcher?.fetch { [weak self] result in // nõrk viide self-le
            guard let self = self else { return } // kontroll, kas self eksisteerib
            // tulemuse töötlemine
        }
    }
}

class DataFetcher {
    var completionHandler: ((Result<String, Error>) -> Void)?

    func fetch(completion: @escaping (Result<String, Error>) -> Void) {
        self.completionHandler = completion
        // Asünkroonne operatsioon...
    }
}