SWReveal TableViewController - how to launch to different ViewControllers? - swift

I'm using the SWReveal slide out menuing system.
The menu is generated from an array, and all works fine. E.g.
arrayOfCellData = [cellData(cell : 1, text : "Angles", image : #imageLiteral(resourceName: "Angles.png")),
cellData(cell : 2, text : "Area", image : #imageLiteral(resourceName: "Area.png")),
When I tap on a particular menu option I want to segue to a different ViewController. Here is the code that I have been using which doesn't work.
The idea that Row 1 invokes segue A and 2 segue B...
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(indexPath.row == 1 ){
let vc: AnyObject! = self.storyboard?.instantiateViewController(withIdentifier: "A")
self.performSegue(withIdentifier: "A", sender: self)
self.show(vc as! A, sender: vc)
NSLog("A")
}
if(indexPath.row == 2 ){
let vc: AnyObject! = self.storyboard?.instantiateViewController(withIdentifier: "B")
self.performSegue(withIdentifier: "B", sender: self)
self.show(vc as! B, sender: vc)
NSLog("B")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let backItem = UIBarButtonItem()
backItem.title = " "
navigationItem.backBarButtonItem = backItem
if segue.identifier == "A", let nextScene = segue.destination as? A {
nextScene.categoryCounter = 1
}
if segue.identifier == "B", let nextScene = segue.destination as? B {
nextScene.categoryCounter = 2
}
}

With SWRevealViewController it is best to not use segues in storyboard and instead contract your reveal view controller programmatically. Try this, in your didSelectRowAtIndexPath method add the following to your code.
// Here I get the view controllers I am interested in
let frontStoryboard = UIStoryboard(name: "YourStoryboard", bundle: .main)
let frontVC = frontStoryboard.instantiateInitialViewController()
let rearStoryboard = UIStoryboard(name: "YourOtherStoryboard", bundle: .main)
let rearVC = rearStoryboard.instantiateInitialViewController()
// Construct the SWRevealViewController with your view controllers
if let revealVC = SWRevealViewController(rearViewController: rearVC, frontViewController: frontVC) {
revealVC.modalTransitionStyle = .crossDissolve // Set segue transition
present(revealVC, animated: true, completion: nil) // Segue to view controller
}

Related

if let editItemVC = segue.destination as? ItemDetailViewController {} doesn't work

i have two segues in this tableViewController, but the downcasting in prepare(for: segue) doesn't work.
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
print("into segue")
super.prepare(for: segue, sender: sender)
switch segue.identifier {
case "addItem":
print("addItem Segue")
if let addItemVC = segue.destination as? ItemDetailViewController {
print("if let done")
addItemVC.container = container
} else {
print("WTF")
}
case "editItem":
print("editItem Segue")
if let editItemVC = segue.destination as? ItemDetailViewController {
guard let selectedItemCell = sender as? PriorityListTVCell else {
fatalError("Unexpected sender: \(String(describing: sender))")
}
guard let indexPath = tableView.indexPath(for: selectedItemCell) else {
fatalError("The selected cell is not being displayed by the table")
}
editItemVC.editedInfo = list[indexPath.row]
print("passed indexPath.row: \(indexPath.row)")
editItemVC.container = container
}
default:
break
}
}
if i click "add" button, in the console it'll print out
into segue
addItem Segue
WTF
not sure why the downcasting doesn't work, does it have anything to do with segue types of destination?
Thanks for help!
This
if let addItemVC = segue.destination as? ItemDetailViewController {
won't work if the destination vc isn't of type ItemDetailViewController meaning you need to assign the class name in IB , for help you can do
print(type(of:segue.destination))
For navigation do
if let nav = segue.destination as? UINavigationController ,
let addItemVC = nav.viewControllers?.first as? ItemDetailViewController {}

Swift: Pass data from a view controller to a navigation controller

I want to pass data from a view controller to another but I've a Navigation controller between them, so there's a "present" function instead a "performSegue".
private func IniciarMainAdmin(){
let mainAdmin = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let mainAdminNVC = mainAdmin.instantiateViewController(withIdentifier: "NCMainAdmin") as? NCMainAdmin else{
return
}
present(mainAdminNVC, animated: true, completion: nil)
}
I've tried with this code but it didn't work for me:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destViewController = segue.destination as! NCMainAdmin
let secondViewcontroller = destViewController.viewControllers.first as! NCMenuAdmin
secondViewcontroller.adminUserData = "This is a test"
}
Notes:
NCMainAdmin is the Navigation Controller
NCMenuAdmin is the first View Controller of the Navigation Controller
Thanks!
For your code prepare(for to trigger , you need to create a segue from the sender vc to the navigation , so either
private func IniciarMainAdmin(){
let mainAdmin = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let mainAdminNVC = mainAdmin.instantiateViewController(withIdentifier: "NCMainAdmin") as? NCMainAdmin else{
return
}
let first = mainAdminNVC.viewControllers.first as! NCMenuAdmin
first.adminUserData = "This is a test"
present(mainAdminNVC, animated: true, completion: nil)
}
OR
self.performSegue(withIdentifier:"id",sender:nil)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destViewController = segue.destination as! NCMainAdmin
let secondViewcontroller = destViewController.viewControllers.first as! NCMenuAdmin
secondViewcontroller.adminUserData = "This is a test"
}

Swift 3 Dismiss after performing segue

I have three controllers connected with segues.
Controller one is MyNotif, controller 2 is AddNotif and controller three is SelectInterval.
From controller 2 I have a segue to controller 3 and then back to controller 2.
This is because in controller 3 i will select from a tableview a value (string) which will be inserted in a field in controller 2.
When the segue from 3 to 2 is performed the controller is not dismissed. This means that if from controller 2 I press the back button (I do not use a navigation controller, the back button is a simple button. Here's the code:)
#IBAction func backBtnPressed(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
I will land on controller 3 instead that on controller one.
To summarise I'm trying to achieve this:
From controller 1 I go to controller 2. From here I can go to controller 3, select the string I need, perform the segue, go back to controller 2 (and till here everything works fine). Once back on controller 2 i f I click the back button i would like to go back on controller 1 (now what happens is that i go back on controller 3).
A bit complicate explain... hopefully it is a bit clear.
here's my segue code:
AddNotif:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SelectRepeatInterval" {
if let destination = segue.destination as? SelectRepeatIntervalVC {
destination.selectedRepeatingInterval = repeatingInterval
}
}
}
SelectInterval:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRow(at: indexPath)! as! SelectRepetaIntervalCell
selectedInterval = currentCell.repeatIntervalLbl.text!
performSegue(withIdentifier: "IntervalSelected", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "IntervalSelected" {
if let destination = segue.destination as? AddNotificationVC {
destination.repeatingInterval = selectedInterval
}
}
}
What you are looking for is presentingViewController https://developer.apple.com/documentation/uikit/uiviewcontroller/1621430-presentingviewcontroller
if let destination = self.presentingViewController as? AddNotificationVC {
destination.repeatingInterval = selectedInterval
}
dismiss(animated: true, completion: nil)
Here is the complete code
tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
// Get Cell Label
let currentCell = tableView.cellForRow(at: indexPath)! as! SelectRepetaIntervalCell
selectedInterval = currentCell.repeatIntervalLbl.text!
if let destination = self.presentingViewController as? AddNotificationVC {
destination.<your textfield name>.text = selectedInterval
}
dismiss(animated: true, completion: nil)
}

Segue and Button programmatically swift

I am using iCarousel and I have to create my own button. I want to pass data from the button made programmatically to another view, but I don't have a segue identifier because I created the button programmatically. I don't know if it is possible to create the identifier of the segue programmatically.
button.addTarget(self, action: #selector(buttonAction3), for: .touchUpInside)
button.setTitle("\(titulos[index])", for: .normal)
tempView.addSubview(button)
let myImage = UIImage(named: "modo4.png") as UIImage?
button.setImage(myImage, for: .normal)
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "modo") as! Modo1ViewController
self.present(viewController, animated: false, completion: nil)
if segue.identifier == "" {
if let destination = segue.destination as? Modo1ViewController {
destination.nomb = nombres
}
}
Create seuge
Assign identifier
and your button target
#IBAction func button_clicked(_ sender: UIButton) {
self.performSegue(withIdentifier: "segueToNext", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueToNext" {
if let destination = segue.destination as? Modo1ViewController {
destination.nomb = nombres // you can pass value to destination view controller
// destination.nomb = arrayNombers[(sender as! UIButton).tag] // Using button Tag
}
}
}
in your case, if you use self.present and you want to send data between views. Try this:
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "modo") as! Modo1ViewController
viewController.nomb = nombres
self.present(viewController, animated: false, completion: nil)
I don't know how to set segue's identifier but I think code above can help
If you want do to easier work, you can create segue in IB (Interface Builder) and set it's identifier, then use
performSegue:withIdentifier:sender

Bad Exception on swipe action cell Swift

I'm making an app that is sending information about text inside of cells to a WebViewController using swipe actions. The swipe action is:
let sendToWebsite = UITableViewRowAction(style: .Default, title: "Website")
{ (action, indexPath) in
self.performSegueWithIdentifier("yourSegueIdentifier", sender: nil)
}
sendToWebsite.backgroundColor = UIColor.blueColor()
return [sendToWebsite]
}
This works fine but I also have two segues coming from the same View Controller, to two other VC's. The first segue(recipeDetail) is when you tap directly on the cell and works fine, but the second segue(yourSegueIdentifier) is a button that appears when you activate the slide action on the cell and does't work.
the segues:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "recipeDetail") {
let indexPath = self.tableView!.indexPathForSelectedRow
let destinationViewController: DetailViewController = segue.destinationViewController as! DetailViewController
destinationViewController.recipe = recipes[indexPath!.row]
}
else if segue.identifier == "yourSegueIdentifier"
{
let indexPath = self.tableView!.indexPathForSelectedRow
let nextVC: WebViewController = segue.destinationViewController as! WebViewController
nextVC.recipe = recipes[indexPath!.row]
}
}
On the line
nextVC.recipe = recipes[indexPath!.row]
indexPath is coming out as nil and giving the following error message
Well it looks like on the swipe action, the tableView doesn't register the "indexPathForSelectedRow" method.
What you could alternatively do is setup a global swipeIndex variable
class ViewController: UIViewController{
var swipeIndex : Int!
//Code, code, code...
and then set it once the swipe action is called.
let sendToWebsite = UITableViewRowAction(style: .Default, title: "Website")
{ (action, indexPath) in
self.swipeIndex = indexPath.row
self.performSegueWithIdentifier("yourSegueIdentifier", sender: nil)
}
sendToWebsite.backgroundColor = UIColor.blueColor()
return [sendToWebsite]
}
and then:
else if segue.identifier == "yourSegueIdentifier"
{
let indexPath = self.tableView!.indexPathForSelectedRow
let nextVC: WebViewController = segue.destinationViewController as! WebViewController
nextVC.recipe = recipies[self.swipeIndex]
}
}