Search code examples
swiftmacossegueswift4nsslider

Can't pass value from FirstVC to SecondVC using segue


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


Solution

  • 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?) {