Sobes.tech
Middle

Mesélj a capture list-ről Swift-ben.

sobes.tech MI

Válasz az MI-től

A Swiftben a capture listet használják a változók explicit kezelésére a zárványok (closures) által történő elfogásakor. Ez segít elkerülni az erős ciklusokat, különösen akkor, amikor a self-et használják zárványokon belül, amelyek osztályokon belül vannak. A fő elfogási típusok: weak és unowned.

Elfogási típus Leírás Mikor használjuk
weak A változót opcionálisként fogja el, nem növelve a hivatkozásszámot. Az értéke nil lehet. Amikor az objektum, amit elfogunk, túléli az elfogott objektumot.
unowned A változót anélkül fogja el, hogy növelné a hivatkozásszámot, de feltételezi, hogy az elfogott objektum életben marad, amíg a zárvány létezik. Nem opcionális. Amikor a zárvány és az elfogott objektum élettartama megegyezik, és az elfogott objektum nem lesz nil a zárvány végéig.

A capture list szintaxisa:

{ [capture list] (paraméterek) -> visszatérési típus in
    // kód
}

Példa a weak self használatára:

class MyClass {
    var value = 0

    func doSomethingLater() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
            guard let self = self else { return } // `nil` ellenőrzése
            self.value += 1
            print("Az érték most \(self.value)")
        }
    }
}

Példa az unowned self használatára:

class ViewController: UIViewController {
    var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        button = UIButton(type: .system)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
    }

    @objc func buttonTapped() {
        // Az `unowned self` ebben az esetben nem szükséges, mivel a gomb létezik, amíg a ViewController is.
        // De ha a zárvány túlélheti a ViewControllert, az `unowned` megfelelő lehet, ha biztosak vagyunk benne,
        // hogy self nem lesz `nil`.
        let action = { [unowned self] in
             self.view.backgroundColor = .blue
        }
        action()
    }
}

Nemcsak self-et, hanem más változókat is elfoghatunk, amelyek elérhetők a zárványban. Például, hogy megőrizzük egy változó értékét a zárvány létrehozásának pillanatában:

func createIncrementer(initialValue: Int) -> () -> Int {
    var currentValue = initialValue
    return { [initialValue] in // Az initialValue érték szerint fogja el
        currentValue += 1
        print("Az eredeti érték \(initialValue)") // Az initialValue megőrzi az eredeti értékét
        return currentValue
    }
}

let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Kimenet: Az eredeti érték 5 volt, majd 6
print(incrementer()) // Kimenet: Az eredeti érték 5 volt, majd 7