Почему ключевое слово "слабый" применяется только к типам протоколов класса и класса
Когда я объявляю переменные как weak
в Swift, я иногда получаю сообщение об ошибке из Xcode:
"Слабый" может применяться только к классу и типу протокола, привязанного к классу.
Мне просто интересно, почему ключевое слово weak
может применяться только к классам и типам протоколов, привязанных к классу? В чем причина этого?
Ответы
Ответ 1
weak
является квалификатором для ссылочных типов (в отличие от типов значений, таких как struct
и встроенных типов значений).
Типы ссылок позволяют иметь несколько ссылок на один и тот же объект. Объект освобождается, когда последняя сильная ссылка перестает ссылаться на него (слабые ссылки не учитываются).
С другой стороны, типы значений присваиваются копией. Счетчик ссылок не применяется, поэтому модификатор weak
не имеет смысла с ними.
Ответ 2
Одной из распространенных причин этой ошибки является то, что вы объявили свой собственный протокол, но забыли наследовать от NSObjectProtocol:
protocol PenguinDelegate: NSObjectProtocol {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
Приведенный выше код выдаст вам ошибку, если вы забудете наследовать от NSObjectProtocol
. Причина в том, что weak
имеет смысл только для ссылочных типов (классов). Таким образом, вы сделаете компилятор менее нервным, четко заявив, что PenguinDelegate предназначен для классов, а не для типов значений.
Ответ 3
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
Если вы набираете класс после своего протокола, он также работает и представляется более подходящим для NSObjectProtocol.
Ответ 4
Ну, на всякий случай, если кто-то еще думает, что в вашем коде все правильно, как я, проверьте, что вы по ошибке не заменили :
на =
.
Вот что у меня было. Это также давало мне ту же ошибку, что и выше:
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate = PenguinDelegate?
}
Но правильный путь:
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
Ты видишь разницу? Мне потребовалось некоторое время, чтобы понять, что вместо двоеточия у меня был знак равенства. Также обратите внимание, что я получил другие ошибки для той же строки, так как решил, что моя первая ошибка, скорее всего, будет реальной проблемой:
- weak
может применяться только к классу и типу протокола, привязанного к классу
: - & л;
Ответ 5
Я узнаю в одном случае, когда у вас даже есть тип класса, но вы все равно получите это сообщение об ошибке.
Например,
class MyVC: UIViewController {
var myText: UITextView = {
[weak self]
let text = UITextView()
// some codes using self
return text
}()
}
Здесь объект UITextView
возвращается из анонимного блока как инициализация var myText
. Я получил сообщение об ошибке такого же типа. Чтобы решить проблему, var
должен быть помечен как lazy
:
class MyVC: UIViewController {
lasy var myText: UITextView = {
[weak self]
let text = UITextView()
// some codes using self
return text
}()
}
Ответ 6
weak
для ARC (автоматический подсчет ссылок). Это означает, что вы не добавляете счетчик ссылок. Поэтому он работает только для Class
. И в Swift вы получите дополнительное значение для безопасности.
Ответ 7
Я пытался захватить свойства типа String и Array для замыкания. Я получил эти ошибки:
"Слабый" может применяться только к классу и типу протокола, привязанного к классу, но не "[String]"
"Слабый" может применяться только к классу и типу протокола, привязанного к классу, но не "Строка"
Я играл некоторое время на детской площадке, и оказалось, что для этих типов достаточно захватить себя.
Ответ 8
Я использовал целевой класс C в swift для scrolView. Я создал IBOutlet этого представления прокрутки. И во время компиляции кода эта ошибка начала показывать.
Поэтому, чтобы решить эту проблему, импортируйте этот класс в заголовок моста
.
импортировать "YourClass.h"
Я использовал Xcode 9.2 с Swift 3.2
Ответ 9
Просто к вашему сведению, а кто не обновился.
После того, как было предложено быстрое предложение SE-0156 https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md, в документации Swift "Раздел протоколов только для классов" https://docs.swift.org/swift-book/LanguageGuide/Protocols.html теперь описывается, как использовать AnyObject вместо класса.
Таким образом, в будущем класс может быть устаревшим.
Ответ 10
weak
работает только для ссылочного типа, поэтому XCode сообщит об ошибке, если вы звоните из struct
(вместо class
).