По моему TextViewTableViewCell
, у меня есть переменная для отслеживания блока и метод настройки, в котором блок передается и назначается.
Вот мой TextViewTableViewCell
класс:
//
// 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)
}
}
}
Когда я использую метод configure в своем cellForRowAtIndexPath
методе, как правильно использовать слабое «я» в блоке, который я передаю.
Вот что я имею без слабого «я»:
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
ОБНОВЛЕНИЕ : я получил следующее, чтобы работать с помощью [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
Когда я делаю [unowned self]
вместо [weak self]
и вынимаю if
заявление, приложение вылетает. Любые идеи о том, как это должно работать с [unowned self]
?
ios
swift
retain-cycle
NatashaTheRobot
источник
источник
Ответы:
Если « я» может быть нулевым в замыкании, используйте « слабое я» .
Если self никогда не будет нулевым в закрытии, используйте [unowned self] .
Если при использовании [unowned self] произойдет сбой, я бы предположил, что self в некоторый момент в этом закрытии равен нулю, поэтому вместо этого вам пришлось использовать [слабое self] .
Мне очень понравился целый раздел из руководства по использованию сильных , слабых и неиспользуемых в замыканиях:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html
Примечание: я использовал термин закрытие вместо блока, который является более новым термином Swift:
Разница между блоком (цель C) и закрытием (Swift) в IOS
источник
unowned
. Не стоит рисковать сбоем вашего приложения.Положите
[unowned self]
перед(text: String)...
в вашем закрытии. Это называется списком захвата и помещает инструкции по владению символами, захваченными в закрытии.источник
** ИЗМЕНЕНО для Swift 4.2:
Как прокомментировал @Koen, swift 4.2 позволяет:
PS: Так как у меня есть некоторые повышающие голоса, я хотел бы рекомендовать чтение об избежании закрытия .
РЕДАКТИРОВАНИЕ: Как прокомментировал @ tim-vermeulen, Крис Латтнер сказал в пятницу 22 января 19:51:29 CST 2016, этот трюк не должен использоваться на себе, поэтому, пожалуйста, не используйте его. Проверьте информацию о не выходящих замыканиях и ответ списка захвата от @gbk. **Для тех, кто использует [слабое я] в списке захвата, обратите внимание, что self может быть нулем, поэтому первое, что я делаю, это проверяю с помощью оператора guard
Если вы задаетесь вопросом, что такое кавычки,
self
- это профессиональный трюк для использования себя внутри замыкания без необходимости менять имя на this , weakSelf или что-то еще.источник
self
(в обратных галочках). Назовите его как-нибудь еще, например nonOptionalSelf, и все будет хорошо.{ [weak self] in guard let self = self else { return }
может использоваться без обратных галочек, и фактически поддерживается: github.com/apple/swift-evolution/blob/master/proposals/…Использовать список захвата
дополнительные объяснения
источник
РЕДАКТИРОВАТЬ: Ссылка на обновленное решение от LightMan
Смотрите решение LightMan . До сих пор я использовал:
Или:
Обычно вам не нужно указывать тип параметра, если он выводится.
Вы можете вообще опустить параметр, если его нет, или если вы ссылаетесь на него, как
$0
в закрытии:Просто для полноты; если вы передаете замыкание функции, а параметр - нет
@escaping
, вам не нужноweak self
:источник
Начиная с версии 4.2 🔸 мы можем сделать:
источник
strongSelf
явно объясняет переменные, означающие / побочный эффект, что хорошо, если код имеет более продолжительную природу. цените ваше мнение, хотя, не знал, что C ++ использовал такие фразы.guard let self = self else { return }
для распаковки[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
источник
Вы можете использовать [Слабое Я] или [Неизвестное Я] в списке захвата до ваших параметров блока. Список захвата является необязательным синтаксисом.
[unowned self]
здесь хорошо работает, потому что клетка никогда не будет равна нулю. В противном случае вы можете использовать[weak self]
источник
Если вы терпите крах, чем вам, вероятно, нужно [слабое я]
Я предполагаю, что блок, который вы создаете, как-то все еще подключен.
Создайте prepareForReuse и попробуйте очистить блок onTextViewEditClosure внутри него.
Посмотрите, предотвращает ли это сбой. (Это всего лишь предположение).
источник
Закрытие и сильные опорные циклы [О программе]
Как вы знаете, закрытие Swift может захватить экземпляр. Это означает, что вы можете использовать
self
внутри замыкания. Особенноescaping closure
[О] может создатьstrong reference cycle
который. Кстати, вы должны явно использоватьself
внутриescaping closure
.Быстрое закрытие имеет
Capture List
функцию, которая позволяет избежать такой ситуации и разорвать ссылочный цикл, потому что не имеют сильной ссылки на захваченный экземпляр. Элемент списка захвата представляет собой паруweak
/unowned
и ссылка на класс или переменную.Например
weak
- предпочтительнее, используйте его, когда это возможноunowned
- используйте его, когда вы уверены, что время жизни экземпляра владельца больше, чем замыканиеисточник