Создать слабые селекторы / функции в Swift - PullRequest
0 голосов
/ 16 апреля 2020

Я использую RxSwift в проекте и обнаружил, что когда я связываюсь напрямую с селектором, он фиксирует сильную ссылку от себя, и deinit не вызывается.

Мне было интересно, как заставить селектор / забаву c иметь дело только с weak ссылкой на себя.

viewModel.title
  .drive(onNext: updateTitle)
  .disposed(by: disposeBag)

func updateTitle(_ title: String) {
  navigationItem.title = title
}

Я пробовал

func updateTitle(_ title: String) {
  weak var weakSelf = self
  weakSelf?.navigationItem.title = title
}

Но все же deinit не вызывается.


Конечно, одним из решений будет удаление function полностью

viewModel.title
  .drive(onNext: { [weak self] title in 
    self?.updateTitle(title)
  )
  .disposed(by: disposeBag)

, но я не потеряю краткий обязательный код.

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Играя с этим, я обнаружил, что вы можете получить синтаксис вроде:

viewModel.title
  .drive(onNext: weakCapture(self, method: YourViewController.updateTitle))
  .disposed(by: disposeBag)

Лекарство хуже болезни, но это немного забавно. Вот определение вспомогательного метода:

func weakCapture<T: AnyObject, A1>(
    _ target: T,
    method: @escaping (T) -> (A1) -> Void
) -> (A1) -> Void {
    return { [weak target] arg in
        guard let strongTarget = target else { return }
        method(strongTarget)(arg)
    }
}

Вот пример использования:

var c: C? = C()
let weaklyCapturedFooMethod = weakCapture(c!, method: C.foo)

weaklyCapturedFooMethod(123) // Runs foo(i: 123)
print(c as Any)
c = nil

weaklyCapturedFooMethod(123) // does nothing

Это не очень приятно. : P

Я бы порекомендовал просто использовать: { [weak self] self?.updateTitle($0) }

0 голосов
/ 16 апреля 2020

После некоторого взгляда, по-видимому, вы не можете пошутить c слабым. Это не то, как работает программирование.

Я придумал это решение:

viewModel.title
  .drive(onNext: updateTitle)
  .disposed(by: disposeBag)

lazy var updateTitle: ((String) -> Void)? = { [weak self] _ in
  self?.navigationItem.title = $0
}

Это решение, но все же любопытно, можем ли мы сделать так, чтобы селектор захватывал слабые ссылки.

...