0

I have two ViewControllers connected via Show segue. I need to pass NSSlider's value from ViewController to SecondViewCotroller.

So, moving slider in ViewController a variable updates in SecondViewController.

How to update a value of imagesQty variable?

// FIRST VIEW CONTROLLER

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var slider: NSSlider!
    @IBOutlet weak var photosLabel: NSTextField!

    @IBAction func segueData(_ sender: NSSlider) {
        photosLabel.stringValue = String(slider.intValue) + " photos"
        self.performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "SegueIdentifierForSecondVC"), sender: slider)
    }

    func prepare(for segue: NSStoryboardSegue, sender: NSSlider?) {
        if segue.identifier!.rawValue == "SegueIdentifierForSecondVC" {
            if let secondViewController =
            segue.destinationController as? SecondViewController {
                secondViewController.imagesQty = slider.integerValue
            }
        }
    }
}

and

// SECOND VIEW CONTROLLER

import Cocoa

class SecondViewController: NSViewController {

    var imagesQty = 30  

    override func viewWillAppear() {

    super.viewWillAppear()
    self.view.wantsLayer = true

    print("viewWillAppear – Qty:\(imagesQty)")

    //let arrayOfViews: [NSImageView] = [view01...view12]

    let url = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop/ArrayOfElements")
    do {
        let fileURLs = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]).reversed()
        let photos = fileURLs.filter { $0.pathExtension == "jpg" }

        for view in arrayOfViews {
            //"imagesQty" is here
            let i = Int(arc4random_uniform(UInt32(imagesQty-1)))
            let image = NSImage(data: try Data(contentsOf: photos[i]))
            view.image = image
            view.imageScaling = .scaleNone
        }
    } catch {
        print(error)
    }
}

enter image description here enter image description here

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220

2 Answers2

1

You can‘t change the value because the var is defined in the function and not in the class.

Make your var a class property and it should work.

class SecondViewController: UIViewController {

var imagesQty: Int = 30

...

}
finn
  • 653
  • 3
  • 15
1

First of all the purpose and benefit of NSStoryboardSegue.Identifier is to create an extension to be able to avoid literals.

extension NSStoryboardSegue.Identifier {
    static let secondVC = NSStoryboardSegue.Identifier("SegueIdentifierForSecondVC")
}

Then you can write

self.performSegue(withIdentifier: .secondVC, sender: slider)

and

if segue.identifier! == .secondVC { ...

This error occurs because imagesQty is declared in viewWillAppear rather than on the top level of the class.

Change it to

class SecondViewController: NSViewController {

    var imagesQty = 30 // Int is inferred

    // override func viewWillAppear() {
    //     super.viewWillAppear()
    // }
}

There is another mistake: The signature of prepare(for segue is wrong. It must be

func prepare(for segue: NSStoryboardSegue, sender: Any?) {
vadian
  • 274,689
  • 30
  • 353
  • 361
  • I fixed the code. I'm moving the slider and value isn't changed. Maybe something else? – Andy Jazz Mar 27 '18 at 16:52
  • Is the action connected? Is the segue performed at all? Is the class of the second view controller set to `SecondViewController`? – vadian Mar 27 '18 at 16:54
  • Action is connected (from slider to controller, look at the picture). Class is SecondViewController. How to check if segue is performed? – Andy Jazz Mar 27 '18 at 16:56
  • Set breakpoints, insert `print` lines. Please see the updated answer. – vadian Mar 27 '18 at 16:59
  • override func prepare(for segue: NSStoryboardSegue, sender: Any?) { } is set – Andy Jazz Mar 27 '18 at 17:13
  • print(segue) after secondViewController.imagesQty = Int(slider.intValue) is not working... – Andy Jazz Mar 27 '18 at 17:14
  • Does the identifier of the segue (in IB) match `SegueIdentifierForSecondVC`? – vadian Mar 27 '18 at 17:18
  • Yes, it's SegueIdentifierForSecondVC (I copied-pasted it, no errors) – Andy Jazz Mar 27 '18 at 17:26
  • Then connect the segue to the controller (rather than to the slider) and connect the slider to the IBAction. – vadian Mar 27 '18 at 17:28
  • What's supposed to happen in `viewWillAppear()`? You don't need to override the method if there is no custom code. – vadian Mar 27 '18 at 17:52
  • I connected the segue to the controller (it was connected to slider). Slider was connected to the IBAction, it's ok. I pasted print(imagesQty) in viewWillAppear() – no change! It prints 30. – Andy Jazz Mar 27 '18 at 17:55
  • If the segue is performed the code must work. Force unwrap `let secondViewController = segue.destinationController as! SecondViewController` (remove `if` and the braces). If the code crashes there is a design error – vadian Mar 27 '18 at 17:59
  • Code is not crashed. I removed `if` and `{ }` – Andy Jazz Mar 27 '18 at 18:03
  • viewDidLoad – Qty:30 viewWillAppear – Qty:30 viewDidAppear – Qty:30 – Andy Jazz Mar 27 '18 at 18:05
  • It was in Output area. – Andy Jazz Mar 27 '18 at 18:06
  • Does the slider send 30? Set `imagesQty` to `0` or a negative value. Once again, the code is correct and must work. – vadian Mar 27 '18 at 18:07
  • Regarding the issue the code in your answer is irrelevant. Please debug the code. Is `prepare(for segue` called? Is the line `secondViewController.imagesQty = Int(slider.intValue)` reached? By the way `intValue` returns `Int`, this is another redundant initializer. Again, please don't misuse answers for more information. Edit the question. – vadian Mar 27 '18 at 18:19