No meu TextViewTableViewCell
, eu tenho uma variável para acompanhar um bloco e um método de configuração onde o bloco é passado e atribuído.
Aqui está a minha TextViewTableViewCell
turma:
//
// TextViewTableViewCell.swift
//
import UIKit
class TextViewTableViewCell: UITableViewCell, UITextViewDelegate {
@IBOutlet var textView : UITextView
var onTextViewEditClosure : ((text : String) -> Void)?
func configure(#text: String?, onTextEdit : ((text : String) -> Void)) {
onTextViewEditClosure = onTextEdit
textView.delegate = self
textView.text = text
}
// #pragma mark - Text View Delegate
func textViewDidEndEditing(textView: UITextView!) {
if onTextViewEditClosure {
onTextViewEditClosure!(text: textView.text)
}
}
}
Quando eu uso o método configure no meu cellForRowAtIndexPath
método, como uso adequadamente o self fraco no bloco em que passo.
Aqui está o que eu tenho sem o self fraco:
let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {(text: String) in
// THIS SELF NEEDS TO BE WEAK
self.body = text
})
cell = bodyCell
UPDATE : trabalhei usando o seguinte [weak self]
:
let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {[weak self] (text: String) in
if let strongSelf = self {
strongSelf.body = text
}
})
cell = myCell
Quando eu faço [unowned self]
, em vez de [weak self]
e tirar o if
comunicado, o aplicativo falha. Alguma idéia de como isso deve funcionar [unowned self]
?
ios
swift
retain-cycle
NatashaTheRobot
fonte
fonte
Respostas:
Se o eu puder ser nulo no fechamento, use [eu fraco] .
Se o eu nunca for nulo no fechamento, use [eu sem dono] .
Se estiver falhando quando você usa o [eu não dono], eu acho que esse eu é nulo em algum momento desse fechamento, e é por isso que você teve que usar o [eu fraco] .
Gostei muito de toda a seção do manual sobre o uso de fortes , fracos e sem dono nos fechamentos:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html
Nota: usei o termo encerramento em vez do bloco, que é o termo Swift mais recente:
Diferença entre bloco (objetivo C) e fechamento (Swift) no ios
fonte
unowned
. Não vale a pena o risco de causar um travamento no seu aplicativo.Coloque
[unowned self]
antes(text: String)...
no seu encerramento. Isso é chamado de lista de captura e coloca instruções de propriedade sobre os símbolos capturados no fechamento.fonte
** EDITADO para o Swift 4.2:
Como o @Koen comentou, o swift 4.2 permite:
PS: Como estou tendo alguns votos positivos, gostaria de recomendar a leitura sobre como escapar de fechamentos .
EDITADO: Como @ tim-vermeulen comentou, Chris Lattner disse em 22 de janeiro, 19:51:29 no CST de 2016, esse truque não deve ser usado por conta própria, portanto, não o use. Verifique as informações de fechamento sem escape e a resposta da lista de capturas em @gbk. **Para aqueles que usam [self fraco] na lista de captura, observe que o self pode ser nulo; portanto, a primeira coisa que faço é verificar isso com uma declaração de guarda
Se você está se perguntando o que são as aspas,
self
é um truque profissional para usar o self dentro do fechamento sem precisar mudar o nome para este , fracoSelf ou qualquer outra coisa.fonte
self
(nos backticks). Nomeie algo como nonOptionalSelf e tudo ficará bem.{ [weak self] in guard let self = self else { return }
pode ser usado sem backticks e é realmente suportado: github.com/apple/swift-evolution/blob/master/proposals/…Usar lista de captura
explicações adicionais
fonte
EDIT: Referência a uma solução atualizada por LightMan
Veja a solução do LightMan . Até agora eu estava usando:
Ou:
Geralmente, você não precisa especificar o tipo de parâmetro, se for inferido.
Você pode omitir o parâmetro completamente se não houver nenhum ou se referir a ele como
$0
no fechamento:Apenas por completude; se você estiver passando o fechamento para uma função e o parâmetro não estiver
@escaping
, não precisará deweak self
:fonte
A partir do rápido 4.2, podemos fazer:
fonte
strongSelf
explica explicitamente as variáveis que significam / efeito colateral, o que é bom se o código for de natureza mais longa. aprecio sua opinião, porém, não sabia que o c ++ usava esse fraseado.guard let self = self else { return }
para desembrulhar[weak self]
: github.com/apple/swift-evolution/blob/master/proposals/...Swift 4.2
https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.md
fonte
Você pode usar [self fraco] ou [self não proprietário] na lista de captura antes dos seus parâmetros do bloco. A lista de captura é uma sintaxe opcional.
[unowned self]
funciona bem aqui porque a célula nunca será nula. Caso contrário, você pode usar[weak self]
fonte
Se você está travando, provavelmente precisará de um "eu fraco"
Meu palpite é que o bloco que você está criando ainda está conectado.
Crie um prepareForReuse e tente limpar o bloco onTextViewEditClosure dentro dele.
Veja se isso impede a falha. (É apenas um palpite).
fonte
Encerramento e fortes ciclos de referência [Sobre]
Como você sabe, o fechamento de Swift pode capturar a instância. Isso significa que você pode usar
self
dentro de um fechamento. Especialmenteescaping closure
[About] pode criar umstrong reference cycle
quê. A propósito, você deve usar explicitamente oself
interiorescaping closure
.O fechamento
Capture List
rápido possui um recurso que permite evitar essa situação e interromper um ciclo de referência porque não possui uma referência forte à instância capturada. O elemento Capture List é um par deweak
/unowned
e uma referência à classe ou variável.Por exemplo
weak
- mais preferível, use-o quando for possívelunowned
- use-o quando tiver certeza de que a vida útil do proprietário da instância é maior que o fechamentofonte