how to pass Intergers between view controllers in swift - swift

This is my code and it's not working. LightOrDark and LightDark are Integers and should be equal when the app changes views.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "LightSegue") {
if let MinigameView = segue.destinationViewController as? MinigameView {
self.LightOrDark = MinigameView.LightDark
}
}
}

self.LightOrDark = MinigameView.LightDark this statement sets MinigameView.LightDark to current class's LightOrDark.
You need to set LightDark of MinigameView so your code should be like,
MinigameView.LightDark = self.LightOrDark
And you should follow naming standard. variable or instance name should be start with lower case not upper case.
so your instance name should be lightOrDark and minigameView instead of LightOrDark and MinigameView.
Hope this will help :)

You need to set the destination viewcontroller property
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let destVc = segue.destinationViewController as? MinigameView else {
return
}
destVc.LightOrDark = self.LightDark
}}

This is wrong: self.LightOrDark = MinigameView.LightDark. Change it to:
MinigameView.LightDark = self.LightOrDark

Related

segue if cant access all of them

Hello i have problem because i have a var count that is += 1 when i press a button so, when i update de counter it doesnt function all the segues. for example if the count == 2, i want to acces count == 1 and count == 2
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "modos" {
if count == 1 {
if let destination = segue.destination as? ModosViewController {
destination.nnj1 = nombresJugadores[1]
}
}
if count == 2 {
if let destination = segue.destination as? ModosViewController {
destination.nnj2 = nombresJugadores[2]
}
}
If you truly want to be able to pass as many names as you want to your destination controller, your current approach won't work.
You need to have an array in your destination view controller that new names can be appended to. This way you can just call the index of each item in your destination controller. With your approach, you would have to create an infinite amount of nnj variables, which obviously isn't feasible.
So this would look something like this:
class ModosViewController: UIViewController {
var names: [String] = [String]()
...
}
Then what you can do is just change the prepareForSegue func to this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "modos" {
if let destination = segue.destination as? ModosViewController {
destination.names = nombresJugadores
}
}
}
Because now you have an array of names in your origin that you pass onto the destination VC. Hope this helps.

How to use optional binding in switch statement in prepare(segue:)

In swift you can use a cool feature of the switch statement in prepare(segue:) to create cases based on the type of the destination view controller:
Example:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.destination {
case let detailViewController as DetailViewController:
detailViewController.title = "DetailViewController"
}
case let otherViewController as OtherViewController:
otherViewController.title = "OtherViewController"
}
}
However, what if the segue is triggered by a split view controller, so the destination is a navigation controller, and what you really want to do is switch on the class of the navigation controller's top view controller?
I want to do something like this:
case let nav as UINavigationController,
let detailViewController = nav.topViewController as? DetailViewController:
//case code goes here
Where I have the same construct that I use in a multiple part if let optional binding.
That doesn't work. Instead, I have to do a rather painful construct like this:
case let nav as UINavigationController
where nav.topViewController is DetailViewController:
guard let detailViewController = nav.topViewController as? DetailViewController
else {
break
}
detailViewController.title = "DetailViewController"
That works, but it seems needlessly verbose, and obscures the intent. Is there a way to use a multi-part optional binding in a case of a switch statment like this in Swift 3?
I worked out a decent solution to this problem.
It involves doing some setup before the switch statement, and then using a tuple in the switch statement. Here's what that looks like:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let dest = segue.destination
let navTopVC = (dest as? UINavigationController)?.topViewController
switch (dest, navTopVC) {
case (_, let top as VC1):
top.vc1Text = "Segue message for VC1"
case (_, let top as VC2):
top.vc2Text = "Segue message for VC2"
case (let dest as VC3, nil):
dest.vc3Text = "Segue message for VC3"
default:
break
}
}
You might find this extension useful…
extension UIStoryboardSegue {
var destinationNavTopViewController: UIViewController? {
return (destination as? UINavigationController)?.topViewController ?? destination
}
}
Then you can simply…
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.destinationNavTopViewController {
case let detailViewController as? DetailViewController:
// case code goes here
}
Note that the ?? destination makes sure the return value is non-optional, and also allows it to work in places where the destination could also be a non-navigation controller.
I don't think there is a way to do this with switch and case, but you can do something closer to what you are looking for with if and case (Update: as Hamish pointed out, the case isn't even needed for this scenario) or just normal if let:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let nav = segue.destination as? UINavigationController,
let detailViewController = nav.topViewController as? DetailViewController {
detailViewController.title = "DetailViewController"
}
if let otherViewController? = segue.destination as? OtherViewController {
otherViewController.title = "OtherViewController"
}
}
Since your switch statement in this example isn't really going to ever be verified by the compiler as handling all cases (because you need to create a default case), there is no added benefit to using switch instead of just if let
Optional binding doesn't really lend itself to switches like you're trying to do.
I understanding the desire to use switches rather than simple if and if else, but it's a bit different conceptually from what switch is meant to do.
Anyway, here are the two options I use for most situations
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.destination {
case is DetailViewController:
segue.destination.title = "DetailViewController"
case is OtherViewController:
segue.destination.title = "OtherViewController"
default:
break
}
}
or
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let controller = seuge.destination as? DetailViewController {
controller.title = "DetailViewController"
}
else if let controller = seuge.destination as? OtherViewController {
controllercontroller.title = "OtherViewController"
}
}
In my opinion, you should use segue identifiers for controlling flow in this switch. But to answer your question, this should work for you.
switch (segue.destination as? UINavigationController)?.topViewController ?? segue.destination {
...
}
The thing is, according to grammar, you have only one pattern (in your case it is binding) per item in a case item list. Since you have only one item on the input but want to use two patterns, you either want to normalize input (which is in this case appropriate as you can see above) or extend item list (which is inappropriate in this case but I show an example below).
switch ((segue.destination as? UINavigationController)?.topViewController, segue.destination) {
case (let tvc, let vc) where (tvc ?? vc) is DetailViewController:
// TODO: If you await your DetailViewController in navigation or without.
break
case (let tvc as DetailViewController, _):
// TODO: If you await your DetailViewController in navigation but other vc is not in a navigation vc.
default:
fatalError()
}

Assign to underscore [duplicate]

my code before the migation to Swift 2.0:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "RhymeFavoriten") {
// pass data to next view
let dest = segue.destinationViewController as! FavoritenViewController
let source = segue.sourceViewController as! RhymeViewController // !!!!!!
dest.favoritenType = 1
dest.delegate = self
}
}
the migration told me to change it to
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "RhymeFavoriten") {
// pass data to next view
let dest = segue.destinationViewController as! FavoritenViewController
_ = segue.sourceViewController as! RhymeViewController // !!!!!!!!!!
dest.favoritenType = 1
dest.delegate = self
}
or
func textSelected(selectedText:String, selectedType:Int) {
var fullTextArr = text.componentsSeparatedByString("\n")
var myArray = [String]() // !!!!!!
to
func textSelected(selectedText:String, selectedType:Int) {
var fullTextArr = text.componentsSeparatedByString("\n")
_ = [String]() // !!!!!!!!!
I can´t see, what is _ = standing for :-(
_ is a placeholder. It means that the values assigned to _ are ignored.
Xcode's migration tool made this changes because it has detected that you didn't use source or myArray anywhere, thus replaced these variables by the placeholder.
Now instead of being assigned to a variable, the returning result of segue.sourceViewController as! RhymeViewController and the returning result of [String]() are ignored.
The returning result is ignored but the expression is still evaluated at runtime: if it has side effects, these effects will occur.
So if you actually don't need these instructions you should get rid of them entirely.

Passing same object context 2 two separate view controllers

I have a managedObject that is being passed from 1 view controller to another the first pass works fine but when I try to pass the next object after the relationship has been set it doesn't send anything and comes back as either nil or if I try to use other methods comes back with a syntax error. The code I am using for the view controllers is as follows
View Controller 1, The first object set:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let identifier = segue.identifier {
switch identifier {
case "popOver":
if let VC = segue.destinationViewController as? ClassDeckNameViewController
{
if let ppc = VC.popoverPresentationController {
VC.modalPresentationStyle = UIModalPresentationStyle.Popover
ppc.permittedArrowDirections = UIPopoverArrowDirection.Any
ppc.delegate = self
}
VC.classSave = (sender as! ClassSelection)
}
default: break
}
}
}
#IBAction func buttonPriest(sender: AnyObject) {
let entity = NSEntityDescription.entityForName("ClassSelection", inManagedObjectContext: classMOC!)
let newObject = ClassSelection(entity: entity!,insertIntoManagedObjectContext: classMOC)
newObject.classname = "Priest"
var error: NSError?
if let err = error {
println(err)
} else {
classMOC?.save(&error)
self.performSegueWithIdentifier("popOver", sender: newObject)
}
}
This passes the object without problem to the second view controller but this is the one that won't pass any further to the final presenting controller offering the user the final selections for their "Deck":
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showCardSelection" {
let detailVC: CardSelectionViewController = segue.destinationViewController as! CardSelectionViewController
detailVC.passedDeckObject = (sender as! Deck)
}
}
#IBAction func enterButton(sender: AnyObject) {
let entityDescription = NSEntityDescription.entityForName("Deck",inManagedObjectContext: managedObjectContext!)
let storeDeck = Deck(entity: entityDescription!,insertIntoManagedObjectContext: managedObjectContext)
storeDeck.deckname = usersDeckName.text
storeDeck.classSelected = classSave!
var error: NSError?
managedObjectContext?.save(&error)
if let err = error {
status.text = err.localizedFailureReason
} else {
usersDeckName.text = ""
status.text = "Deck Saved"
self.performSegueWithIdentifier("showCardSelection", sender: storeDeck)
}
}
I made passedDeckObject a variable of type Deck? in the final view controller to set the final relationship methods I know I am doing something wrong but I am unsure what! Any help with this would be amazing!
This looks to be a misconfiguration issue where the segue is being triggered directly in the storyboard rather than calling your code. As such the sender is a button rather than the new entity instance you're expecting.
To fix, disconnect the segue in the storyboard and connect (if it isn't already) the button to your action method in the view controller.

'bool' is not convertible to 'uint8'

I'm trying to build to-do app using Xcode 6 and Swift. I was able to run the app on Xcode 6 dp2 but after updating to dp7 I'm getting this error:
'bool' is not convertible to 'uint8'.
Here is the function with the error:
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
**if ((segue && segue!.identifier == "showdetails") != nil)**{
var selectedIndexPath:NSIndexPath = self.tableView.indexPathForSelectedRow()
var detailViewController:DetailViewController = segue!.destinationViewController as DetailViewController
detailViewController.toDoData = toDoItems.objectAtIndex(selectedIndexPath.row) as NSDictionary
}
}
The correct way to write that is:
if (segue != nil && segue!.identifier == "showdetails") {
but an even better way is using optional binding:
if let segue = segue {
if (segue.identifier == "showdetails") {
Note that there are other errors about incorrect usage of optionals. This is the modified code that compiles in playground:
if let segue = segue {
if (segue.identifier == "showdetails") {
var selectedIndexPath:NSIndexPath? = self.tableView.indexPathForSelectedRow()
if let selectedIndexPath = selectedIndexPath {
var detailViewController:DetailViewController = segue.destinationViewController as DetailViewController
detailViewController.toDoData = toDoItems.objectAtIndex(selectedIndexPath.row) as NSDictionary
}
}
}
indexPathForSelectedRow returns an optional, so you have to account for that.
Update: as pointed out by #MartinR, segue is no longer optional, so you can solve the problem by simply updating the function signature, and its implementation should look like:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showdetails") {
var selectedIndexPath = self.tableView.indexPathForSelectedRow()
if let selectedIndexPath = selectedIndexPath {
var detailViewController = segue.destinationViewController as DetailViewController
detailViewController.toDoData = toDoItems.objectAtIndex(selectedIndexPath.row) as NSDictionary
}
}
}
First of all when I read the documentation what I read is :
func prepareForSegue(_ segue: UIStoryboardSegue, sender sender: AnyObject?)
UIKit seems to be updated in Beta7 to use less optionals. So segue may be not optional.
Then even if your function signature is good, you are comparing a Boolean to nil.
This (segue && segue!.identifier == "showdetails") is a boolean. A boolean is either true or false.
And at the very end, here is the best practice to unwrap a variable :
if let mySafeVariable = myOptionalVariable {
if mySafeVariable.attribute == <Whatever> {
}
}
You should. No, wait, you must read the Swift free iBooks.