1

I'm quite new to programming in general - and to Swift in particular - but there's one thing I've been pounding my head on recently.

I'm trying to access a variable in a 'parent' class - but I can't work out how to get there.

I've already looked at other posts that seem to cover the same thing - Access variable in different class - Swift , How to create a global variable? , Access variable in different class - Swift and Pass variables from one ViewController to another in Swift - but none of them seem to do exactly what I want.

I'm wanting to be able to have a window of Preference settings, which I can set and have apply to variables in my 'main' class - but I can't see how to pass the variables from the Preferences window up to the 'main' class.

Here's an example in which I've defined an NSTextField on my first ViewController, which I want to be able to modify in my second ViewController and have it update in the first. My actual application will probably need many such instances, in order to provide a full set of modifiable preferences.

//  ViewController.swift

import Cocoa


class ViewController: NSViewController {


lazy var sheet2ViewController: NSViewController = {
    return self.storyboard!.instantiateControllerWithIdentifier("sheet2") as! NSViewController}()


@IBAction func openPanel(sender: AnyObject) {
    displaySheet()
}


@IBOutlet weak var textField: NSTextField!


var textString : String = "" {
    didSet {
        textField.stringValue = textString
    }
}


func displaySheet() {

    self.presentViewControllerAsSheet(sheet2ViewController)

}



override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
}

override var representedObject: AnyObject? {
    didSet {
    // Update the view, if already loaded.
    }
}


}



//  SecondViewController.swift

import Cocoa

class SecondViewController: NSViewController {

@IBOutlet weak var textField2: NSTextField!


@IBAction func closeButton(sender: AnyObject) {
    ???.textString = textField2.stringValue // How to address the ViewController variable here?
    self.dismissController(self)

}


override func viewDidLoad() {
    super.viewDidLoad()
    // Do view setup here.
}

}

As you see, the issue I have is in the closeButton function in the SecondViewController class - how to pass the value back up to the textString variable in the ViewController class?

I've been looking at delegation and NSNotificationCenter - but I really don't know if I'm barking up the right trees here - it feels like I'm going to have to implement something much more complicated than I would expect for such a (seemingly) simple requirement.

Any suggestions very welcome - thanks.

Community
  • 1
  • 1
Moisie
  • 45
  • 1
  • 6

2 Answers2

0

In an OSX storyboard NSViewController has a property presentingViewController which represents the parent view controller.

In SecondViewController you can refer to the presenting controller with

let parentViewController = presentingViewController as! ViewController
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thanks Vadian - but when I try this, I get the error: 'Instance member 'presentingViewController' cannot be used on type 'SecondViewController''. – Moisie May 03 '16 at 08:56
  • You are calling the method on the type but you have to call it on the instance, the line must be inside a method. – vadian May 03 '16 at 08:59
  • @vadian self.presentingViewController as the name suggests showing the view itself not the parent. – Sazzad Hissain Khan Aug 11 '18 at 05:44
  • Actually the *present**ed*** controller is the current controller. The *present**ing*** controller is in fact the parent view controller. – vadian Aug 11 '18 at 06:16
0

Try using delegates and protocols. When you create the child you set its delegate to be the parent. One of the delegate methods can have a parameter that the child can set and the parent(or the class that implements the delegate) can read.

A small example:

protocol MyProtocol {
    func turnedOn(val:Bool) -> Void
}

class Headlights {
    var delegate:MyProtocol?

    func test1() -> Void {
        if let del = delegate {
            del.turnedOn(true)
        }
    }
}

class Car:MyProtocol {
    var lamp:Headlights

    init() {
        lamp = Headlights()
        lamp.delegate = self
    }

    func turnedOn(val:Bool) -> Void {

    }
}
Horatiu
  • 151
  • 2
  • 12
  • Thanks Horatiu. I think I'm going to need to spend more time studying protocols and delegation - it just hasn't clicked for me yet. In the meantime, Vadian's answer gets me what I need to do for the moment. – Moisie May 03 '16 at 09:32