Почему ключевое слово "слабый" можно применять только к классу и типу протокола, привязанного к классу

Когда я объявляю переменные как weak в Swift я иногда получаю сообщение об ошибке из Xcode:

"Слабый" может применяться только к классу и типу протокола, привязанного к классу.

Мне просто интересно, почему ключевое слово weak может применяться только к классу и типу протокола, привязанного к классу? В чем причина этого?

9 ответов

Решение

weak является классификатором для ссылочных типов (в отличие от типов значений, таких как structs и встроенные типы значений).

Типы ссылок позволяют иметь несколько ссылок на один и тот же объект. Объект освобождается, когда последняя сильная ссылка перестает ссылаться на него (слабые ссылки не учитываются).

Типы значений, с другой стороны, назначаются копией. Подсчет ссылок не применяется, поэтому 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

  1. weak не для типа значения.
  2. слабый попадает в картину только для класса.

"weak" может применять все, что унаследовано от классов или типов протоколов, связанных с классом

  1. Протокол класса: протокол ViewControllerDelegate: class {func getInformationk(value: String?)}
  2. NSObjectProtocol:

    протокол ViewControllerDelegate: NSObjectProtocol { func getInformation(value: String?) }

weak работает только для ссылочного типа, поэтому Xcode сообщит об ошибке, если вы звоните из struct (вместо того class).

Другие вопросы по тегам