Reputation: 58093
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)
}
}
}
Upvotes: 0
Views: 1829
Reputation: 285074
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])
Upvotes: 2
Reputation: 26036
@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)
}
Upvotes: 1