Ответ 1
Это звучит как ошибка. {[unowned self] in self.twinkle()}
должен работать тождественно с {[weak self] in self!.twinkle()}
Это действие SpriteKit повторяется, называя себя закрытием завершения. Он использует закрытие, а не SKAction.repeatActionForever()
, потому что ему нужно генерировать случайную переменную каждое повторение:
class Twinkler: SKSpriteNode {
init() {
super.init(texture:nil, color:UIColor.whiteColor(), size:CGSize(width:10.0, height:10.0))
twinkle()
}
func twinkle() {
let rand0to1 = CGFloat(arc4random()) / CGFloat(UINT32_MAX)
let action = SKAction.fadeAlphaTo(rand0to1, duration:0.1)
let closure = {self.twinkle()}
runAction(action, completion:closure)
}
}
Я думаю, что я должен использовать [unowned self]
, чтобы избежать сильного опорного цикла с закрытием. Когда я это сделаю:
let closure = {[unowned self] in self.twinkle()}
Он выходит из строя с ошибкой: _swift_abortRetainUnowned
. Но если я использую [weak self]
вместо:
let closure = {[weak self] in self!.twinkle()}
Выполняется без ошибок. Почему [weak self]
работает, но [unowned self]
ломается? Должен ли я использовать любой из них здесь?
Объект Twinkler
строго упоминается в другом месте программы, как дочерний элемент другого node. Поэтому я не понимаю, как нарушается ссылка [unowned self]
. Он не должен быть освобожден.
Я попытался реплицировать эту проблему за пределами SpriteKit с помощью dispatch_after()
, но я не смог.
Это звучит как ошибка. {[unowned self] in self.twinkle()}
должен работать тождественно с {[weak self] in self!.twinkle()}
Если self может быть nil в закрытии, используйте [слабый я].
Если self никогда не будет равным нулю в использовании закрытия, используйте [unowned self].
Если он сбой, когда вы используете [unowned self], тогда self, вероятно, является нулевым в какой-то момент в этом закрытии, поэтому вам нужно будет использовать [слабый я].
Примеры из документации довольно хороши для пояснения при использовании strong, слабых и незанятых в закрытии:
Недавно я столкнулся с подобной катастрофой. В моем случае иногда у объекта, получившего новую инициализацию, был тот же самый адрес памяти, что и освобожденный. Однако код будет выполнен просто отлично, если два объекта имеют другой адрес памяти.
Итак, это мое сумасшедшее объяснение. Когда быстрая ссылка на закрытие и проверить его список захвата, он проверяет, был ли объект освобожден или нет, если переменная в списке захвата говорит "unowned". Он не выполняет проверку, если объект помечен как "слабый".
Так как объект гарантированно никогда не был ник в закрытии, он никогда не будет там вообще сбой.
Итак, вероятно, ошибка языка. И мое занятие - это использование слабых, а не неодолимых.
Чтобы не получить ошибку, это должно быть:
let closure = {[weak self] in self?.twinkle()}
not
let closure = {[weak self] in self!.twinkle()}
Восклицательный знак после разворота силы, который выдает ошибку на ноль. Unowned выдаст ошибку, если self - это нуль, как разворачивание силы. При выполнении любого из этих двух вариантов вы должны использовать и защищать, или если инструкция для защиты от нуля.
Это только мое чтение документации, но здесь теория.
Подобно слабым ссылкам, неопубликованная ссылка не удерживает сильную фиксацию на экземпляре, на который она ссылается. В отличие от слабой ссылки, однако, считается, что неизменная ссылка всегда имеет значение. Из-за этого неизменная ссылка всегда определяется как не необязательный тип. [источник]
Вы сказали, что объект Twinkler
сильно привязан как дочерний элемент другого node, но дети SKNode
являются неявно развернутыми опциями. Моя ставка заключается в том, что проблема заключается не в том, что self
освобождается, но при попытке создать закрытие Swift отказывается при создании неопубликованной ссылки на необязательную переменную. Таким образом, [weak self]
- это правый список захвата закрытия, который можно использовать здесь.