@sensation77_666

Как обратиться из своего класса к классу ViewController для изменения IBOutlet или вызова методов?

Здравствуйте. Требуется изменять IBOutlet класса ViewController из своего класса или иного класса.
Сейчас сделано обращение через главное окно (NSApplication.shared.mainWindow), но происходит краш при деактивации окна, mainWindow становится, как я понял nil.
Подскажите, пожалуйста, как правильно реализовать обращение к классу, для изменения IBOutlet или вызова методов?

Swift 4, OSX
  • Вопрос задан
  • 613 просмотров
Пригласить эксперта
Ответы на вопрос 1
maestrro712
@maestrro712
 iOS Developer
Описываемый вами подход не самый удачный. ViewController неспроста так называется, именно он управляет всем view и его содержимым, соответственно, изменять свойства у IBOutlet'а должен только он. Чтобы избежать соблазна, лучше сразу декларировать все IBOutlet как private.
Вместо вашего подхода лучше сделать так, чтобы ViewController был оповещен о произошедших изменениях и соответствующе апдейтил свой view. Сделать это можно многими способами, вот лишь некоторые из них:

1) У вашего класса логики есть делегат. ViewController в методе viewDidLoad находит экземпляр вашего класса и назначает себя делегатом:

class ViewController: NSViewController {
    
    @IBOutlet private weak var usernameLabel: NSTextField!

    func viewDidLoad() {
        super.viewDidLoad()
        let someInstance = //тут мы находим ваш экземляр (к примеру, он синглтон)
        someInstance.delegate = self
    }
}

extension ViewController: SomeInstanceDelegate {
    func updateUsernameOnUI(_ username: String) {
        usernameLabel.stringValue = username
    }
}


2) Ваш класс логики может оповещать своих обзерверов и ViewController становится обзервером:

class ViewController: NSViewController {
    
    @IBOutlet private weak var usernameLabel: NSTextField!

    func viewDidLoad() {
        super.viewDidLoad()
        let someInstance = //тут мы находим ваш экземляр (к примеру, он синглтон)
        someInstance.addObserver(self)
    }
}

extension ViewController: SomeInstanceObserver {
    func usernameUpdated(_ username: String) {
        usernameLabel.stringValue = username
    }
}


3) Если никак не получается при инициализации связать класс логики и ViewController (что, в общем, не гуд), можно использовать NotificationCenter:

class ViewController: NSViewController {
    
    @IBOutlet private weak var usernameLabel: NSTextField!

    func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(usernameUpdate(:)), 
                                                                       name: Notification.Name("usernameUpdated"), object: nil)
    }
}

extension ViewController {
    @objc func usernameUpdate(_ notification: Notification) {
        guard let username = notification.userInfo?["username"] as? String else {
              return
        }
        usernameLabel.stringValue = username
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы