5

私はARCと強い参照サイクルを調べていて、私のこのコードに出くわしました:

class TestClass: UIView {
  let button: UIButton = {
    let view = UIButton()
    view.frame = CGRect(x: 50, y: 50, width: 200, height: 200)
    view.backgroundColor = .blue
    view.translatesAutoresizingMaskIntoConstraints = false
    view.setTitle("Button", for: .normal)
    view.addTarget(self, action: #selector(buttonClicked), for: .touchUpInside)
    return view
  }()

  @objc private func buttonClicked() {
    print("Clicked")
  }

  override init(frame: CGRect) {
    super.init(frame: frame)
    print("Object of TestClass initialized")
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  deinit {
    print("Object of TestClass deinitialized")
  }
}

selfクロージャー内のメソッドでの参照addTargetは、強い参照サイクルを作成していないようです。

誰かが理由を説明できますか?

UIViewまた、コンパイラから継承を削除すると、不平を言い始めることに気付きました: Use of unresolved identifier 'self'.

誰かがこれも説明できますか?なぜこの場合に発生し、最初のケースでは発生しないのですか?

4

1 に答える 1

3

これはあなたが思っているものではないので、保持サイクルではありません:)self

初期値を持つプロパティは、初期化子が実行される前でも「実行」され、これらのプロパティselfに対して、このタイプの高階関数を指します。

(TestClass) -> () -> TestClass

したがって、インスタンスに実際にアクセスするのではなくstatic、デフォルト値を持つすべてのプロパティの初期化を行う のようなメソッドにアクセスします。これが、保持サイクルがない理由です。

addTarget最初の引数の値を受け入れるため、これは型規則に違反しないため、コンパイラはそこにインスタンスAny?を渡さなくても文句を言いません。NSObject

後で動作を確認すると、たとえば、ボタンが UI 階層に追加されてタップされた場合に何が起こるかを確認すると、興味深いことがわかります。ランタイムは、非オブジェクトがターゲットとして渡されたことを認識し、ターゲットとアクションに null 値を設定します。

ここに画像の説明を入力

于 2018-03-08T08:03:44.887 に答える