Почему ключевое слово "слабый" можно применять только к классу и типу протокола, привязанного к классу
Когда я объявляю переменные как weak
в Swift я иногда получаю сообщение об ошибке из Xcode:
"Слабый" может применяться только к классу и типу протокола, привязанного к классу.
Мне просто интересно, почему ключевое слово weak
может применяться только к классу и типу протокола, привязанного к классу? В чем причина этого?
9 ответов
weak
является классификатором для ссылочных типов (в отличие от типов значений, таких как struct
s и встроенные типы значений).
Типы ссылок позволяют иметь несколько ссылок на один и тот же объект. Объект освобождается, когда последняя сильная ссылка перестает ссылаться на него (слабые ссылки не учитываются).
Типы значений, с другой стороны, назначаются копией. Подсчет ссылок не применяется, поэтому weak
Модификатор с ними не имеет смысла.
Одной из распространенных причин этой ошибки является то, что вы объявили свой собственный протокол, но забыли наследовать от NSObjectProtocol:
protocol PenguinDelegate: NSObjectProtocol {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
Приведенный выше код выдаст вам ошибку, если вы забудете наследовать от NSObjectProtocol
, Причина в том, что weak
имеет смысл только для ссылочных типов (классов). Таким образом, вы сделаете компилятор менее нервным, четко заявив, что PenguinDelegate предназначен для классов, а не для типов значений.
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
Если вы набираете class после вашего протокола, он также работает и кажется более подходящим, чем для NSObjectProtocol.
Ну, на всякий случай, если кто-то еще думает, что у вас все правильно в вашем коде, как я, проверьте, что вы по ошибке не заменили :
по =
,
Вот что у меня было. Это также давало мне ту же ошибку, что и выше:
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
может применяться только к классу и типу протокола, привязанного к классу
:-<
Я обнаружил в одном случае, когда у вас даже есть тип класса, но все равно вы получаете это сообщение об ошибке.
Например,
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
}()
}
Просто к вашему сведению, а кто не обновился. После того, как быстрое предложение SE-0156 https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md было реализовано, имеется в Swift docs раздел "Протоколы только для класса" https://docs.swift.org/swift-book/LanguageGuide/Protocols.html теперь описано использование AnyObject вместо класса. Таким образом, в будущем класс может быть устаревшим.
weak
для ARC(Автоматический подсчет ссылок). Это значит не добавлять счетчик ссылок. Так что это работает только для Class
, А в Swift вы получите дополнительное значение для безопасности.
Я пытался захватить свойства типа String и Array для замыкания. Я получил эти ошибки:
"Слабый" может применяться только к классу и типу протокола, привязанного к классу, но не "[String]"
"Слабый" может применяться только к классу и типу протокола, привязанного к классу, но не "Строка"
Я немного поиграл на детской площадке, и оказалось, что для этих типов достаточно захватить себя.
Я использовал объективный класс C в Swift для scrolView. Я создал IBOutlet этого представления прокрутки. И при компиляции кода эта ошибка начала проявляться.
Таким образом, чтобы решить эту проблему, импортируйте этот класс в заголовок моста.
импорт "YourClass.h"
Я использовал Xcode 9.2 с Swift 3.2
- weak не для типа значения.
- слабый попадает в картину только для класса.
"weak" может применять все, что унаследовано от классов или типов протоколов, связанных с классом
- Протокол класса: протокол ViewControllerDelegate: class {func getInformationk(value: String?)}
NSObjectProtocol:
протокол ViewControllerDelegate: NSObjectProtocol { func getInformation(value: String?) }
weak
работает только для ссылочного типа, поэтому Xcode сообщит об ошибке, если вы звоните из struct
(вместо того class
).