#swift
#swift
Вопрос:
Привет, у меня есть 2 протокола, второй из которых имеет и ссылку на первый тип протокола, а также возвращает self
для этой ссылки. вот код.
protocol MainViewModelInput {
func loginButtonAction()
func registerButtonAction()
}
protocol MainViewModelProvider {
var input: MainViewModelInput { get }
}
extension MainViewModelProvider where Self: MainViewModelInput {
var input: MainViewModelInput { return self }
}
итак, когда я реализую это так, создает ли это утечку памяти?
class MainViewModel: MainViewModelProvider, MainViewModelInput {
private let router: AnyRouter<MainRoute>
init(router: AnyRouter<MainRoute>) {
self.router = router
}
}
extension MainViewModel {
func loginButtonAction() {
router.trigger(.login)
}
func registerButtonAction() {
router.trigger(.register)
}
}
Моя идея заключается в том, что, если MainViewController
создается объект типа MainViewModel
, а input
также содержится ссылка на этот объект, он никогда не будет выпущен, я не прав?
Спасибо.
Комментарии:
1. Создайте
input
aweak var
, который потребует, чтобы ваш протокол был протоколом класса2. Спасибо, я просто хотел знать, нужно ли это? потому что, возможно, в других случаях кто-то захочет использовать его для структур, разве это не возможно?
3. Хорошо, я не смотрел достаточно близко. Поскольку
input
это вычисляемое свойство, оно не создает ссылку, так что, я думаю, у вас все хорошо.4. хм, поскольку он возвращает только self, а не назначает delegate как self, это не приведет к утечке, я правильно понял?
5. В вашем расширении протокола вы определили
input
как вычисляемое свойство только для получения, так что да, все будет в порядке.
Ответ №1:
Обычно вы хотите, чтобы ваш делегат был a weak var
, чтобы избежать циклов сохранения в случаях, подобных вашему — именно так шаблон делегирования реализуется, например, UIKit
в таких классах, как UITableView
Однако в вашем случае вы определяете input
переменную как вычисляемое свойство, доступное только для получения. Вычисляемые свойства в Swift работают во многом как функция — они ничего не хранят, они просто предоставляют средства для косвенного извлечения некоторых значений.
Это может сработать, но вам нужно быть особенно осторожным. Пример: давайте изменим ваш код, например, так:
class MainViewModel: MainViewModelProvider, MainViewModelInput {
private let router: AnyRouter<MainRoute>
var input: MainViewModelInput?
init(router: AnyRouter<MainRoute>) {
self.router = router
input = self
}
}
Что мы сделали: мы переопределили реализацию input
property по умолчанию — это больше не вычисляемое свойство. И мы также ввели утечку памяти — теперь self содержит сильную ссылку на себя.
Итак, в целом: ваша идея может сработать, но только если вы будете очень осторожны, чтобы никогда не переопределять input
свойство для хранения и ссылки self
.
Ответ №2:
Что я хотел бы сделать, так это создать функцию, которая проверяет, так ли self
MainViewModelInput
это.
if let modelInput = self as? MainViewModelInput {
// Here you should have access to protocol implementation
}