Sobes.tech
Junior

Co je to uzávěr?

sobes.tech AI

Odpověď od AI

Závěr (closure) ve Swiftu je samostatný blok funkčnosti ({}), který lze předat a použít v kódu. Závěry mohou zachytit a uložit odkazy na jakékoli konstanty a proměnné z kontextu, ve kterém jsou definovány.

Příklady použití:

  • Jako argumenty funkcí (například Completion Handlers).
  • Pro definování chování při iteraci kolekcí (například pomocí metod map, filter, reduce, sorted).
  • Pro odložené provádění kódu.

Syntaxe:

// Základní syntaxe
{ (parametry) -> návratovýTyp in
    příkazy
}

// Příklad závěru, který přijímá Int a vrací String
let integerToString: (Int) -> String = { (number: Int) -> String in
    return "Číslo: \(number)"
}

Vlastnosti:

  • Automatické zachytávání proměnných (capturing values).
  • Možnost definovat závěry bez explicitního určení typů parametrů a návratové hodnoty (syntaktický cukr).
  • Použití zkrácených jmen parametrů ($0, $1 atd.).
  • Syntaxe závěrečného bloku (trailing closure syntax).

Zachytávání proměnných:

Závěr může zachytit proměnné z okolí. Výchozí chování je zachytávání odkazem. Pokud je závěr použit po tom, co původní proměnná opustila oblast platnosti, závěr si stále uchovává přístup k ní.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0 // Proměnná z vnějšího prostředí
    let incrementer: () -> Int = { // Závěr
        runningTotal += amount // Zachytává runningTotal a amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // Výstup: 10
print(incrementByTen()) // Výstup: 20

Seznamy zachytávání (Capture Lists):

Používají se k explicitnímu určení, jak mají být proměnné zachyceny - hodnotou nebo odkazem, a také k prevenci silných cyklů odkazů (retain cycles).

class MyClass {
    var value = 0

    lazy var myClosure: () -> Void = { [self, value] in // Zachytávání self odkazem, value hodnotou
        print("Hodnota self.value: \(self.value)")
        print("Zachycená hodnota: \(value)")
    }

    deinit {
        print("Instance MyClass byla uvolněna")
    }
}

Pro prevenci silných cyklů při zachytávání objektů tříd se používá syntaxe [weak self] nebo [unowned self].

class ViewController {
    var dataFetcher: DataFetcher?

    func fetchData() {
        dataFetcher?.fetch { [weak self] result in // slabé zachycení self
            guard let self = self else { return } // kontrola existence self
            // zpracování result
        }
    }
}

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

    func fetch(completion: @escaping (Result<String, Error>) -> Void) {
        self.completionHandler = completion
        // Asynchronní operace...
    }
}