Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 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

enter image description here Я использовал целевой класс 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).