Middle
Fale sobre a lista de captura em Swift.
sobes.tech IA
Resposta da IA
A lista de captura em Swift é usada para gerir explicitamente a captura de variáveis por closures. Isto ajuda a evitar ciclos fortes de referências, especialmente ao trabalhar com self em closures usados dentro de classes. Os principais tipos de captura são: weak e unowned.
| Tipo de captura | Descrição | Quando usar |
|---|---|---|
weak |
Captura a variável como opcional, sem aumentar o contador de referências. O seu valor pode tornar-se nil. |
Quando o objeto do closure pode sobreviver ao objeto capturado. |
unowned |
Captura a variável sem aumentar o contador de referências, mas assume-se que o objeto capturado viverá enquanto o closure existir. Não é opcional. | Quando o objeto do closure e o objeto capturado têm o mesmo tempo de vida, e o objeto capturado não será nil antes do encerramento do closure. |
Sintaxe da lista de captura:
{ [lista de captura] (parâmetros) -> tipoDeRetorno in
// código
}
Exemplo de uso de weak self:
class MyClass {
var value = 0
func doSomethingLater() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let self = self else { return } // Verificação de nil
self.value += 1
print("O valor agora é \(self.value)")
}
}
}
Exemplo de uso de unowned self:
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() {
// unowned self não é necessário neste caso, pois o botão existe enquanto o ViewController existir.
// Mas se o closure pudesse sobreviver ao ViewController, unowned poderia ser adequado se
// tiver a certeza de que self não se tornará nil.
let action = { [unowned self] in
self.view.backgroundColor = .blue
}
action()
}
}
Pode capturar não só self, mas também quaisquer outras variáveis acessíveis no closure. Por exemplo, para guardar o valor de uma variável no momento da criação do closure:
func createIncrementer(initialValue: Int) -> () -> Int {
var currentValue = initialValue
return { [initialValue] in // Captura initialValue por valor
currentValue += 1
print("O valor inicial era \(initialValue)") // initialValue mantém o seu valor
return currentValue
}
}
let incrementer = createIncrementer(initialValue: 5)
print(incrementer()) // Output: O valor inicial era 5, depois 6
print(incrementer()) // Output: O valor inicial era 5, depois 7