S
S
sensation77_6662018-01-04 03:06:09
Cocoa
sensation77_666, 2018-01-04 03:06:09

How can I access the ViewController class from my class to change the IBOutlet or call methods?

Hello. It is required to change the IBOutlet of the ViewController class from its own class or another class.
Now a call has been made through the main window (NSApplication.shared.mainWindow), but a crash occurs when the window is deactivated, mainWindow becomes, as I understand it, nil.
Tell me, please, how to correctly implement a class call to change IBOutlet or call methods?
Swift 4 OS X

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vyacheslav Beltyukov, 2018-01-11
@maestrro712

The approach you describe is not the best. ViewController is called so for a reason, it is he who manages all the view and its contents, respectively, only he should change the properties of IBOutlet. To avoid the temptation, it is better to immediately declare all IBOutlets as private.
Instead of your approach, it's better to make the ViewController aware of the changes that have occurred and update its view accordingly. There are many ways to do this, here are just a few:
1) Your logic class has a delegate. The ViewController in the viewDidLoad method finds an instance of your class and assigns itself as a delegate:

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) Your logic class can notify its observers and ViewController becomes an observer:
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) If you can’t connect the logic class and ViewController during initialization (which, in general, is not good), you can use 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
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question