#swift
#swift
Вопрос:
У меня есть класс:
class ViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
...
NotificationCenter.default.addObserver(
self,
selector: #selector(self.onDealLaunched),
name: Notification.Name("newDealLaunched"),
object: nil)
}
@objc func onDealLaunched(notification: NSNotification) {
let deal = notification.object as! SimpleSaveGame.deal
let i = projectCollection.count
let indexPath = IndexPath(row: i, section: 0)
let projectDeal: project = project(...)
projectCollection.append(projectDeal)
activeDeals.append(deal)
projectCollectionView!.numberOfItems(inSection: 0)
projectCollectionView.insertItems(at: [indexPath])
projectCollectionView.reloadData()
}
@IBAction func corpoButtonPressed(_ sender: Any) {
let vcCorpo = UIStoryboard(name: "Corpo", bundle: nil).instantiateViewController(withIdentifier: "CorpoViewController") as! CorpoViewController
vcCorpo.currentRound = second
vcCorpo.yearlyTaxIncome = gameVariables[14].value
NotificationCenter.default.addObserver(
self,
selector: #selector(self.onReturnCorpo),
name: Notification.Name("corpoBackButtonPressed"),
object: nil)
self.present(vcCorpo, animated: true, completion: nil)
}
}
Затем у меня есть CorpoViewController, который представляет пользовательский UITableView, и если пользователь нажимает кнопку, он показывает всплывающее окно
class CorpoViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
...
@objc func onLaunchButtonPressed(notification: NSNotification) { // it is launched when player presses negotiate button
dealId = notification.object as! Int
NotificationCenter.default.removeObserver(self, name: Notification.Name("dealLaunchButtonPressed"), object:dealId)
NotificationCenter.default.addObserver(
self,
selector: #selector(self.onPopupClosed),
name: Notification.Name("negotiationPopupClosed"),
object: nil)
self.negotiatedDeal = self.deals[self.dealId]
popup = NegotiationPopup(dealId: self.dealId, deal: self.negotiatedDeal, corpo: self.corpos[self.deals[self.dealId].corpo])
self.view.addSubview(popup)
}
@objc func onPopupClosed(notification: NSNotification) {
NotificationCenter.default.removeObserver(self, name: Notification.Name("negotiationPopupClosed"), object:nil)
negotiatedDeal = notification.object as! SimpleSaveGame.deal
if (negotiatedDeal.status == 2) {
addActiveDeal(deal: negotiatedDeal)
negotiatedDeal.status = 4
deals.remove(at: dealId)
}
}
override func viewDidLoad() {
super.viewDidLoad()
corpoTableView.delegate = self
corpoTableView.dataSource = self
corpoTableView.register(CorpoCell.self, forCellReuseIdentifier: "cellId")
NotificationCenter.default.addObserver(
self,
selector: #selector(self.onLaunchButtonPressed),
name: Notification.Name("dealLaunchButtonPressed"),
object: nil)
planTimer()
}
}
Класс, реализующий:
class CorpoCell: UITableViewCell {
...
@IBAction func launchButtonPressed(_ sender: UIButton) {
NotificationCenter.default.post(name: Notification.Name("dealLaunchButtonPressed"), object: launchButton.tag)
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupView()
}
}
И класс, представляющий всплывающее окно:
class NegotiationPopup: UIView {
...
@objc fileprivate func animateOut() {
self.removeFromSuperview()
NotificationCenter.default.post(name: Notification.Name("negotiationPopupClosed"), object: self.negotiatedDeal)
}
}
@objc fileprivate func cancelButtonPressed() {
...
animateOut()
}
}
Моя проблема в том, что при закрытии всплывающего окна метод animateOut() запускается один раз, но метод @objc func onPopupClosed запускается много раз. Количество раз зависит от того, сколько раз я закрываю CorpoViewController, а затем снова открываю его.
Поэтому я предполагаю, что у меня есть несколько экземпляров CorpoViewController в памяти, но я не знаю, как это подтвердить и как это исправить.
Комментарии:
1. Вы не предоставили достаточно информации. Очевидно, вы ожидаете
onPopupClosed
, что вас вызовут через уведомление. Но вы никогда не показываете нам, куда вы добавляете наблюдателя с помощью селектора дляonPopupClosed
. Самым простым объяснением было бы просто то, что вы добавляете одного и того же наблюдателя несколько раз, но угадать это невозможно, поскольку вы полностью опустили соответствующий код.2. @matt Спасибо за комментарий, я обновляю свой вопрос.
3. Спасибо Мэтту за предложение. Я заменил observer, который указал, что всплывающее окно было закрыто с помощью delegate, и это каким-то образом устранило проблему. 🙂
4. Хорошо, хорошо, теперь вы показали больше кода. Все дело в действительно плохом использовании уведомлений. Уведомления не являются правильным способом передачи сигнала через ваш код.
Ответ №1:
Я заменил observer, который указал, что всплывающее окно было закрыто с помощью delegate, и это каким-то образом устранило проблему.