Swiftで変数をweak
として宣言すると、Xcodeからエラーメッセージが表示されることがあります。
「弱い」は、クラスおよびクラスにバインドされたプロトコルタイプにのみ適用できます
キーワードweak
がクラスおよびクラスにバインドされたプロトコルタイプにしか適用できないのはなぜだろうと思っていましたか?その背後にある理由は何ですか?
weak
は、参照型の修飾子です(struct
sや組み込みの値型などの値型とは異なります)。
参照タイプを使用すると、同じオブジェクトへの複数の参照を作成できます。最後の強い参照が参照を停止すると、オブジェクトの割り当てが解除されます(弱い参照はカウントされません)。
一方、値タイプはコピーによって割り当てられます。参照カウントは適用されないので、weak
修飾子はそれらに対して意味をなしません。
このエラーの一般的な理由の1つは、自分がプロトコルを所有していると宣言したが、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?
}
プロトコルの後にクラスを入力すると同様に機能し、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
は、クラスおよびクラスにバインドされたプロトコルタイプにのみ適用できます
:-<
weak
は、ARC(自動参照カウント)用です。参照カウントを追加しないことを意味します。したがって、Class
に対してのみ機能します。また、Swiftでは、セキュリティのオプション値を取得します。
あるケースでは、クラスタイプさえ持っていても、このエラーメッセージが表示される場合があります。
例えば、
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
}()
}
参考までに、誰も更新されていません。 Swift提案SE-0156 https://github.com/Apple/Swift-evolution/blob/master/proposals/0156-subclass-existentials.md が実装された後、そこにSwift docs "Class-Only Protocols section"にあります https://docs.Swift.org/Swift-book/LanguageGuide/Protocols.html に記載されていますclassの代わりにAnyObjectを使用します。そのため、:classは将来廃止される可能性があります。
クロージャーのString型とArray型のプロパティをキャプチャしようとしました。私はこれらのエラーを受け取りました:
「弱い」は、「[String]」ではなく、クラスおよびクラスにバインドされたプロトコルタイプにのみ適用できます。
「弱い」は、「String」ではなく、クラスおよびクラスにバインドされたプロトコルタイプにのみ適用できます。
私は遊び場でしばらく遊びましたが、結局のところ、これらのタイプには自己をキャプチャするだけで十分です。