我正在使用MVVM创建一个举重计算器应用程序(Swift 4),并且已经尝试了2天来弄清楚为什么应该已经死亡的视图模型仍在响应UserDefaults.defaultsDidChange
事件通知。
CalculatorLiftEventViewModelFromLiftEvent
。
CalculatorLiftEventViewModelFromLiftEvent
对象CalculatorLiftEventViewModelFromLiftEvent
分配给CalculatorViewController
的viewModel属性,替换应用启动时创建的UserDefaults.defaultsDidChange
通知点击计算器屏幕上的+(新)按钮时会发生以下情况:
@objc fileprivate func onNewButtonTapped(_ sender: UIBarButtonItem) {
let newLiftEvent = dataManager.createNewLiftEvent()
viewModel = CalculatorLiftEventViewModelFromLiftEvent(withLiftEvent: newLiftEvent, dataManager: dataManager)
setupView()
}
以下是CalculatorLiftEventViewModelFromLiftEvent
的初始化方式:
init(withLiftEvent liftEvent: LiftEventRepresentable, dataManager: CoreDataHelper) {
self.modelLiftEvent = liftEvent
self.liftName = Dynamic("\(modelLiftEvent.lift.liftName)")
self.weightLiftedTextField = Dynamic(modelLiftEvent.liftWeight.value)
self.repetitionsTextField = Dynamic("\(modelLiftEvent.repetitions)")
self.oneRepMaxTextField = Dynamic(modelLiftEvent.oneRepMax.value)
self.unitsTextField = Dynamic("\(UserDefaults.weightUnit())")
self.weightPercentages = Dynamic( [ : ] )
self.dataManager = dataManager
super.init()
subscribeToNotifications()
}
更新:以下是deinit
中的addObserver
和CalculatorLiftEventViewModelFromLiftEvent
。请注意,我没有使用基于块的观察。
deinit {
print("I got to the deinit method")
unsubscribeFromNotifications()
}
func subscribeToNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(liftNameDidChangeNotification(_:)),
name: NSNotification.Name(rawValue: LiftEventNotifications.LiftNameDidChangeNotification),
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(weightUnitDidChangeNotification(_:)),
name: NSNotification.Name(rawValue: LiftEventNotifications.WeightUnitDidChangeNotification),
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(roundingOptionDidChangeNotification(_:)),
name: NSNotification.Name(rawValue: UserDefaultsNotifications.roundingOptionDidChangeNotification),
object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.defaultsDidChange), name: UserDefaults.didChangeNotification,
object: nil)
}
--- END UPDATE
我在转到SettingsViewController
时传递了modelLiftEvent:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
switch identifier {
case a:...
case b:...
case "SettingsSegue":
if let nav = segue.destination as? UINavigationController {
let destinationViewController = nav.topViewController as! SettingsViewController
destinationViewController.dismissalDelegate = self
let settingsViewModel = SettingsViewModelFromLiftEvent(withLiftEvent: self.viewModel.modelLiftEvent)
destinationViewController.settingsViewModel = settingsViewModel
destinationViewController.dataManager = dataManager
settingsViewModel.dataManager = dataManager
}
最后,在CalculatorLiftEventViewModelFromLiftEvent
中,我在此处设置了一个断点,因为当视图模型听到UserDefaults.defaultsDidChange
通知时会调用此点。此时,我还验证了这个CalculatorLiftEventViewModelFromLiftEvent
是旧版本,而不是我点击+按钮时创建的新版本:
@objc func defaultsDidChange(_ notification: Notification) {
let oneRepMax = modelLiftEvent.calculateOneRepMax()
guard oneRepMax.value != 0.0 else { return }
let weightPercentages = getWeightPercentages(weight: oneRepMax.value)
self.weightPercentages.value = weightPercentages
weightLiftedTextField.value = modelLiftEvent.liftWeight.value
repetitionsTextField.value = "\(modelLiftEvent.repetitions)"
oneRepMaxTextField.value = modelLiftEvent.oneRepMax.value
}
我已经阅读了大量关于物品生命周期的文档,但却找不到任何有用的东西。我希望当创建新的CalculatorLiftEventViewModelFromLiftEvent
并将其分配给`CalculatorViewController的viewModel属性时,它将替换对旧的$content = new \SendGrid\Content("text/html", "<html><body>some text here</body></html>");
$mail = new \SendGrid\Mail($from, $subject, $to, $content);
的引用,它将不再存在。显然,这不是发生的事情。
有没有人知道为什么当我从没有值(除了0.0)的计算器视图(步骤3)进入设置然后再回来时,会显示先前的提升事件值?
答案 0 :(得分:0)
我已经修复了清除计算器,更改默认公式以及返回计算器屏幕后显示的先前liftEvent
的问题。
在CalculatorViewController
上,点击+按钮时,我不是创建新的viewModel并将其分配给viewModel属性,而是要求我的AppDelegate同时创建一个新的CalculatorViewController
和CalculatorLiftEventViewModelFromLiftEvent
使用launchCalculatorViewController
方法在应用启动时执行此操作。
CalculatorViewController
中的原始代码:
@objc fileprivate func onNewButtonTapped(_ sender: UIBarButtonItem) {
let newLiftEvent = dataManager.createNewLiftEvent()
viewModel = CalculatorLiftEventViewModelFromLiftEvent(withLiftEvent: newLiftEvent, dataManager: dataManager)
self.percentagesTableView.reloadData()
setupView()
}
现在CalculatorViewController
中的新代码:
@objc fileprivate func onNewButtonTapped(_ sender: UIBarButtonItem) {
(UIApplication.shared.delegate as? AppDelegate)?.launchCalculatorViewController()
}
和AppDelegate
:
func launchCalculatorViewController() {
self.window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let initialViewController: CalculatorViewController = mainStoryboard.instantiateInitialViewController() as? CalculatorViewController {
self.window?.rootViewController = initialViewController
let liftEvent = dataManager.createNewLiftEvent()
let viewModel = CalculatorLiftEventViewModelFromLiftEvent(withLiftEvent: liftEvent, dataManager: dataManager)
initialViewController.viewModel = viewModel
initialViewController.dataManager = dataManager
self.window?.makeKeyAndVisible()
}
}
不幸的是,我确定CalculatorLiftEventViewModelFromLiftEvent
对象永远不会被释放,这告诉我,我有一个强大的参考周期,不会放手:
这将是另一个问题。