Segue doesn't work in macOS

时光毁灭记忆、已成空白 提交于 2019-12-08 09:39:47

问题


I have NSSlider in ViewController that must pass integer value to SecondViewController via segue of type Show and update a View every time I move it. So, moving slider I interactively shuffle images in SecondViewController's window.

I spent a week trying to implement such a behaviour of NSSlider but I failed. Maybe I made wrong connections in Interface Builder. I don't know. If you know any other method to make NSSlider work for shuffling images, tell me, please.

See updated answer for detailed information.

Really appreciate any help!!!

ViewController

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var slider: NSSlider!

    @IBAction func passData(_ sender: NSSlider) {        
        func prepare(for segue: NSStoryboardSegue, sender: NSSlider?) {
            if segue.identifier!.rawValue == "SegueIdentifierForSecondVC" {
                if let secondViewController = segue.destinationController as? SecondViewController {
                    secondViewController.imagesQuantity = slider.intValue 
                }
            }
        }
    }
}

SecondViewController

import Cocoa

class SecondViewController: NSViewController {

    var imagesQuantity: Int = 1

    override func viewWillAppear() {
        super.viewWillAppear()

        print(imagesQuantity)
    }
}

But it doesn't work. What's wrong in my code?

Any help appreciated.

UPDATED ANSWER

VIEW CONTROLLER

import Cocoa

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

class ViewController: NSViewController {

    @IBOutlet weak var slider: NSSlider!

    @IBAction func segueData(_ sender: NSSlider) {
        self.performSegue(withIdentifier: .secondVC, sender: slider)
    }
    override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
        if segue.identifier! == .secondVC {
            if let secondViewController =
                segue.destinationController as? SecondViewController {
                secondViewController?.imagesQty = slider.integerValue 
            }
        }
    }
}

SECOND VIEW CONTROLLER

import Cocoa

class SecondViewController: NSViewController {

    var imagesQty = 30  

    override func viewWillAppear() {
        super.viewWillAppear()
        //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
            }
        } catch {
            print(error)
        }
    }
}


回答1:


The mistake is not in the code.

You have to connect the segue to the ViewController, not to the WindowController.

Connect the slider action to the IBAction (not to the segue) and the segue from ViewController to SecondViewController (not from the slider).

And if the class of the second view controller is SecondViewController it should be indicated in the window controller. Where does SecondVC come from?

And once again the suggestion to create an extension of NSStoryboardSegue.Identifier

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

and to use it in these two methods. And force cast the segue.destinationController. It must not crash if everything is hooked up properly.

@IBAction func segueData(_ sender: NSSlider) {
    self.performSegue(withIdentifier: .secondVC, sender: nil)
}

override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
    if let identifier = segue.identifier, identifier == .secondVC {
        let secondViewController = segue.destinationController as! SecondViewController
        secondViewController.imagesQty = slider.integerValue
    }
}  

Finally NSImage got its own initializer taking an URL

let image = NSImage(contentsOf: photos[i])



回答2:


@IBAction func passData(_ sender: NSSlider) {        
    func prepare(for segue: NSStoryboardSegue, sender: NSSlider?) {
        if segue.identifier!.rawValue == "SegueIdentifierForSecondVC" {
            if let secondViewController = segue.destinationController as? SecondViewController {
                secondViewController.imagesQuantity = slider.intValue 
            }
        }
    }
}

Should be

@IBAction func passData(_ sender: NSSlider) {        

}

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

Because you have a method inside another while they should be one after the other.

Now, you need to modify passData(_sender:). You need to call inside performSegue(withIdentifier:sender) inside it.
If will trigger at some point prepare(for:sender:). I'm saying at "some point" because there is at least a shouldPerformSegue(withIdentifier:sender:) call before the prepare(for:sender:) is called.

So now do:

@IBAction func passData(_ sender: NSSlider) {        
    self.performSegue(withIdentifier: "SegueIdentifierForSecondVC"  sender:nil)
}


来源:https://stackoverflow.com/questions/49478503/segue-doesnt-work-in-macos

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!