prepareForSegue in SWRevealViewController with Swift - swift

I'm trying to write prepareForSegue in SWRevealViewController with Swift.
Here is my code:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)
{
if(segue!.identifier == "segueName")
{
var someText = "Text"
var rvc:newViewController = segue!.destinationViewController as newViewController
rvc.topText = someText
}
}
In newViewController I have topText as NSString
Of course I got nil text because I should make SWRevealViewControllerSegue but I don't know how it should look in Swift

I've found the solution.
First of all need to configure SWRevealControllerSegue. In swift it should looks like:
if(segue.isKindOfClass(SWRevealViewControllerSegue))
{
var rvcs: SWRevealViewControllerSegue = segue as SWRevealViewControllerSegue
var rvc:SWRevealViewController = self.revealViewController()
rvcs.performBlock = {(rvc_segue, svc, dvc) in
var nc:UINavigationController = dvc as UINavigationController
rvc.pushFrontViewController(nc, animated: true)
}
}
Second. XCode beta works bad right now with IBOutlet and segue like this. With variable everything is ok.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.isKindOfClass(SWRevealViewControllerSegue))
{
var rvcs: SWRevealViewControllerSegue = segue as SWRevealViewControllerSegue
var rvc:SWRevealViewController = self.revealViewController()
rvcs.performBlock = {(rvc_segue, svc, dvc) in
var nc:UINavigationController = self.revealViewController().frontViewController as UINavigationController
nc.setViewControllers([dvc], animated: true)
self.revealViewController().setFrontViewPosition(FrontViewPositionLeft, animated: true)
}
}
}

This doesn't work with the latest version. The release notes state:
Took a cleaner approach to storyboard support. SWRevealViewControllerSegue is now deprecated and you should use SWRevealViewControllerSegueSetController and SWRevealViewControllerSeguePushController instead.
There aren't any swift examples anywhere I can find that explain this though.
The performBlock method no longer exists.
Appreciate any help. It seems impossible to do swift without first learning objective c at the moment :)

What was newViewController? This should work:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)
{
if(segue.identifier == "segueName")
{
let someText = "Text"
let rvc = segue.destinationViewController as SWRevealViewController
rvc.topText = someText
}
}

Related

Trying to switch which photo pops up depending on button clicked Xcode

I am making an app that will display a random quote from a stoic philosopher. Right now, I am stuck on trying to make the correct picture pop up. (User clicks on a Button with the philosopher's name on it, and then a new view pops up with an image of the philosopher and a random quote by him).
class ViewController: UIViewController {
var allQuotes = [String]()
var pictures = [String]()
#IBOutlet var Epictetus: UIButton!
#IBOutlet var Seneca: UIButton!
#IBOutlet var MarcusAurelius: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Create a constant fm and assign it the value returned by FileManager.default (built in system type)
let fm = FileManager.default
// Declares a new constant called path that sets the resource path of ours apps buddle.
// A bundle is a directory containing our compiled program and all our assets
let path = Bundle.main.resourcePath!
// items array will be a constant collection of the names of all the files found in the directory of our app
let items = try! fm.contentsOfDirectory(atPath: path)
// create a loop to go through all of our items...
for item in items {
if item.hasSuffix("jpg"){
pictures.append(item)
}
}
print(pictures)
title = "Stoicism"
if let stoicQuotesURL = Bundle.main.url(forResource: "quotes", withExtension: "txt"){
if let stoicQuotes = try? String(contentsOf: stoicQuotesURL) {
allQuotes = stoicQuotes.components(separatedBy: "\n\n")
}
}
}
#IBAction func buttonTapped(_ sender: UIButton) {
if sender.tag == 0 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[0]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 1 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[1]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 2 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[2]
navigationController?.pushViewController(vc, animated: true)
}
}
}
}
That's the code for my main viewController.
import UIKit
class PictureViewController: UIViewController {
#IBOutlet var picture: UIImageView!
#IBOutlet var imageView: UIImageView!
var selectedImage: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if let imageToLoad = selectedImage {
imageView.image = UIImage(named: imageToLoad)
}
}
override func viewWillAppear(_ animated: Bool) {
// doing it for the parent class
super.viewWillAppear(animated)
// if its a nav Cont then it will hide bars on tap...
}
// now make sure it turns off when you go back to the main screen
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
That's the code for the viewController that has the imageView. Right now, the image that's popping up is always the preset (Marcus Aurelius), even though my code looks correct to me. Obviously it isn't (also, I've already debugged and ensured through print statements that the jpg files add to the pictures array correctly).
Any help would be appreciated.
First of all, this code is really silly:
#IBAction func buttonTapped(_ sender: UIButton) {
if sender.tag == 0 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[0]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 1 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[1]
navigationController?.pushViewController(vc, animated: true)
}
}
else if sender.tag == 2 {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
vc.selectedImage = pictures[2]
navigationController?.pushViewController(vc, animated: true)
}
}
}
Do you see that everything in those lines is identical except for the numbers? So make the number a variable:
#IBAction func buttonTapped(_ sender: UIButton) {
if let vc = storyboard?.instantiateViewController(identifier: "Picture") as? PictureViewController {
print(sender.tag)
vc.selectedImage = pictures[sender.tag]
navigationController?.pushViewController(vc, animated: true)
}
}
See how much shorter and clearer that is? Okay, I've also added a print statement. This will print the tag to the console. You need to make sure that your buttons do have the right tags. If they do, your code should work.

how to pass Intergers between view controllers in 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

Sending Variables with a Segue

I am working on a simple iOS Swift app. The app has 2 view controllers and a button that has been programmed to segue to the other view controller like so:
#IBAction func pushMe(sender: AnyObject) {
self.performSegueWithIdentifier("changeIt", sender: nil)
}
The above works but I want to be able to save 2 variables from the current view controller and make them available to the view controller I am segueing to. So I did this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "changeIt" {
var testVar1 = "Hello"
var testVar2 = "World"
}
}
In the view controller that I am segueing to I added:
var testVar1:String!
var testVar2:String!
The app works but as soon as I try to access testVar1 or testVar2, the app crashes. I am not sure why this isn't working as intended?
Because variables were not initialized, you omitted destination view controller. Use the code below
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "changeIt" {
let dvc = segue.destinationViewController as! YourDestinationViewController
dvc.testVar1 = "Hello"
dvc.testVar2 = "World"
}
}
if segue.identifier == "changeIt" {
var testVar1 = "Hello"
var testVar2 = "World"
}
All you are doing here is making new, completely separate local variables called testVar1 and testVar2. They are not, by some miraculous wishful thinking, the same as the instance properties testVar1 and testVar2 belonging to the view controller you are segueing to. How can they be? That code never even mentions that view controller at all! If you want to set a property of a view controller, you need to talk to that view controller.
Think of it this way. Suppose the Dog class has a name property and you want to set a Dog instance's name. Do you do it by saying this?
let d = Dog()
let name = "Fido"
No! That creates a name, but it isn't the dog's name. You need to say this:
let d = Dog()
d.name = "Fido"
So in your code, you need to use the segue to get a reference to the destination view controller and set its properties.
You can solve it creating the variables on destination ViewController
class OtherViewController : UIViewController {
var testVar1 : String = ""
var testVar2 : String = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var message = "\(self.testVar1) \(self.testVar2)"
print(message)
}
}
The UIStoryboardSegue has a destinationViewController property. It's an instance to the end point view controller you want to reach. Then now you can do this:
class SourceViewController : UIViewController {
//...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//Some code before
var destination = segue.destinationViewController as! OtherViewController
destination.testVar1 = "Hello"
destination.testVar2 = "World"
//Some code after
}
}

'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.

Swift cast fails

So I'm writing this segue method in Swift, but when I unwrap controller, it is always none. Without the as? it just downright fails at runtime. Whats going on?
override func prepareForSegue(segue : UIStoryboardSegue!, sender: AnyObject!) {
if(segue.identifier == "showCoursesSegue") {
var controller = segue.destinationViewController as? EditViewController
controller!.test = true
}
}
This works fine for me in prepare for segue. Tried actually setting the type of controller to EditViewController and removing that ?.
var dst: NoteViewController = segue.destinationViewController as NoteViewController
Do it the Swift way!
func prepareForSegue(segue : UIStoryboardSegue!, sender: AnyObject!) {
switch segue.identifier! {
case "showCoursesSegue":
switch segue.destinationViewController {
case let controller as EditViewController:
controller.test = true
default:
println("segue.destinationViewController is \(segue.destinationViewController)")
}
default:
println("segue.identifier is \(segue.identifier)")
}
}
The issue here was that in IB, the ViewController hadn't been set up as a custom class. I'd post a picture but haven't got enough rep.