SWRevealController setting frontViewController from code - ios

I was debugging my app using Instruments and found out that every time I perform self.revealViewController().pushViewController() memory usage is increasing. I've changed this line to be self.revealViewController().setFront() and now it looks fine, but I am kinda confused about how it works. What do both of these functions do? How should I navigate if I perform this in didSelectRowAt indexPath method like:
case "MenuText":
let targetVC = storyboard!.instantiateViewController(withIdentifier: "AllSelectionsNC") as! UINavigationController
let destinationVC = targetVC.topViewController as! AllSelectionsTableViewController
self.revealViewController().setFront(targetVC, animated: true)
self.revealViewController().setFrontViewPosition(.left, animated: true)
self.setStatusBarStyle(.default)
Am I doing something wrong here? Most of tutorials perform segues using storyboard, but I have to perform them from code

Related

Push New VC from Subview Table View Controller

I have an Arranged Subview (a Table View) within a parent View Controller.
Let's call the parent VC CollectionViewController and the subview (Table VC) ResultsTableViewController.
I've added the table view to my stackview (in CollectionViewController) like this:
let hitsTableController = ResultsTableViewController()
stackView.addArrangedSubview(hitsTableController.tableView)
Then I've implemented didSelectRowAt in the ResultsTableViewController (the subview):
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let hit = hitsSource?.hit(atIndex: indexPath.row)
print("The ID is " + hit?.id)
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ItemDetailViewController") as? ItemDetailViewController
self.navigationController?.pushViewController(vc!, animated: true)
}
}
I'm able to print information about the cell I select (the ID in this case), but I can't figure out how to navigate to the Details View Controller when a cell is pressed.
I've tried this with no luck:
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ItemDetailViewController") as? ItemDetailViewController
self.navigationController?.pushViewController(vc, animated: true)
The code runs, but nothing happens. Any help would be appreciated.
SOLUTION
Add this
addChild(hitsTableController)
hitsTableController.didMove(toParent: self)
before this
stackView.addArrangedSubview(hitsTableController.tableView)
As Frankenstein mentioned below, the problem was that ResultsTableViewController had no access to the navigation stack. That's because I had to make it a child of the parent VC, CollectionViewController. Now I'm able to call this without any problems.
self.navigationController?.pushViewController(vc!, animated: true)
try to force unwrap your objects if the app crash then give us the crash details
let vc = self.storyboard!.instantiateViewController(withIdentifier: "ItemDetailViewController") as! ItemDetailViewController
self.navigationController!.pushViewController(vc, animated: true)
Update: With the details that you've added it has become evident that the issue was that the view controller isn't embedded in a UINavigationController. You see that navigationController is an optional and it get allocated only if the controller is embedded in a UINavigationController. Try this:
let hitsTableController = UINavigationController(rootViewController: ResultsTableViewController())
stackView.addArrangedSubview(hitsTableController.tableView)
Seems the storyboard either has no ItemDetailViewController in it or you've forgotten to set the identifier which seems unlikely in your scenario. Hence I conclude that the ItemDetailViewController is created programmatically. So you should be initializing ItemDetailViewController with the empty initializer for presenting it.
let vc = ItemDetailViewController()
self.navigationController?.pushViewController(vc, animated: true)

Switch tab bar failed programmatically in Swift

I want to switch tabbar item 2 but it always goes to item 1. in the log, it says it goes to item 2 as well but it shows item 1. i am using the segue. viewControllers![1]
if segue.identifier == Constants.Identifiers.goToWinTabFromSearchMatch {
let tabBarController = segue.destination as! UITabBarController
let navController = tabBarController.viewControllers![1] as! UINavigationController
let controller = navController.topViewController as! WinViewController
}
#IBAction func doneToBackToWinTab(_ sender: Any) {
print("i wana back to the win tab")
performSegue(withIdentifier: Constants.Identifiers.goToWinTabFromSearchMatch, sender: nil)
}
I too am confused by your code snippet as it merely declares a bunch of constants, you're not performing any action whatsoever here. To change tabs in UITabViewController, simply use the selectedIndex property (it's a simple Int). Set it to a valid value and voilà.
However, you have a host of problems in your if block regarding optionals. Force-unwrapping and accessing array fields that may not even exist is just asking for trouble. I highly recommend you do it the right way and unwrap them properly via if let.
i.e., your tabBarController.viewControllers![1] as! UINavigationController is virtually like placing a can of kerosene next to an open fire - you don't know when but it will eventually blow up.

Attempt to present whose view is not in the window hierarchy when a cell is tapped

I'm currently working on an app with a UITableViewController. The idea is that when a cell is tapped on, an info page will pop up showing some information about it. So when tapped on, I attempt to present another ViewController in another class. However, the warning shows up and I'm not sure why.
I've tried looking at questions similar to mine on Stackoverflow and other websites, but they don't make much sense to me. Can anyone explain the problem behind this warning and how to fix it?
Some of my code:
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
print("showing item info")
let cell = tableView.cellForRow(at: indexPath)
currentInfo = (cell?.textLabel?.text)!
currentDes = descriptions[indexPath.row]
currentBool = itemBools[indexPath.row]
currentIndexPath = indexPath
showInfo()
}
func showInfo() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ShowInfoViewController") as! ShowInfoViewController
self.present(vc, animated: true, completion: nil)
}
Warning message is:
Attempt to present <Things_to_Do.ShowInfoViewController: 0x100b2fe20> on <Things_to_Do.TableViewController: 0x100b05eb0> whose view is not in the window hierarchy!
Try to add presentation style
Swift 2
vc.modalPresentationStyle = .FormSheet
vc.modalTransitionStyle = .CoverVertical
You are trying to present the ViewController from a class which is not there in the window hierarchy. You need to check self.present(vc, animated: true, completion: nil) whether the self in this line is a ViewController which is added to the window hierarchy before you execute that line.
I found my problem. The problem was cause I had created a segue on the storyboard, connecting a table cell to the new ViewController. By writing code to present the same ViewController, XCode got confused.

Switch between different Views in SWIFT

I read a lot of questions / answers in the stack overflow community about switching between different ViewControllers but I couldn't find the correct answer for my specific problem.
I'm using a NavigationViewController to "connect" all my different viewControllers (ViewController / TableViewController / CollectionViewController)
I have got some classes which aren't depending on a ViewController class. For example to to calculate anything in my "calculate" class.
I'm searching for an easy solution, to switch between all my ViewControllers. And I would like to decide in my "calculate" class e.g. to go one step back in my Navigation ViewController.
In the moment I use this:
Example to switch between two different ViewControllers:
let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewControllerWithIdentifier("StartPage") as! StartPageView
self.presentViewController(vc, animated: true, completion: nil)
PROBLEM: This example only works in a ViewController class and the navigation bar disappears.
Example to go one step back in my NavigationViewController:
self.navigationController?.popViewControllerAnimated(true)
PROBLEM: This example only works in a ViewController class.
EDIT 1:
I found a nice solution to call all my viewControllers with this part of code:
let switchViewController = self.navigationController?.viewControllers[1] as! ScanTableView
self.navigationController?.popToViewController(switchViewController, animated: true)
How can I call this code in a non ViewController class?
Push the new view controller onto your existing navigation stack, rather than presenting it modally:
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("StartPage") as! StartPageView
self.navigationController!.pushViewController(vc, animated: true)

Manual segue with SWRevealViewController in Swift

There is a great blog post over at http://www.appcoda.com/tag/swrevealviewcontroller/ that goes in to setting up SWRevealViewController which is a great component for slide out side menus (https://github.com/John-Lluch/SWRevealViewController)
Unfortunately, there are no swift examples of how to perform a manual segue.
Took a cleaner approach to storyboard support. SWRevealViewControllerSegue is now deprecated and you should use SWRevealViewControllerSegueSetController and SWRevealViewControllerSeguePushController instead.
I've tried something along the lines of:
let navigationController = self.window?.rootViewController as! SWRevealViewController;
let viewController = navigationController.storyboard?.instantiateViewControllerWithIdentifier("ImportFileSelect") as! ImportFileSelect
navigationController.showViewController(viewController, sender: self)
This doesn't work though. Any ideas? I've trawled the web for swift examples, my next step is to learn objective c!
In order to work you'll need to following steps:
You need to instantiate the SWRevealViewController and then attach it
to the root controller.
Then instantiate the destination controller.
Then create a navigation controller and set the destination
controller as the rootViewController
Finally push the navigation controller with SWReveal
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let sw = storyboard.instantiateViewControllerWithIdentifier("SWRevealViewController") as! SWRevealViewController
self.view.window?.rootViewController = sw
let destinationController = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardID") as! NameOfViewController
let navigationController = UINavigationController(rootViewController: destinationController)
sw.pushFrontViewController(navigationController, animated: true)
I've kind of made some progress. I can load in a new view controller, but it doesn't animate in anyway. The code to do this, on a button click is:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("TARGET_VIEW_CONTROLLER") as! UIViewController
var rvc:SWRevealViewController = self.revealViewController() as SWRevealViewController
rvc.pushFrontViewController(vc, animated: true)
Download SWRevealViewController project's zip form Github.
Drag SWRevealViewController.m and SWRevealViewController.h files from zip (SWRevealViewController folder) to your project, and Click “Yes” to the prompted message "Would you like to configure an Objective-C bridging header?"
Take a look at storyboard in RevealControllerStoryboardExample2 project. Design your storyboard with this example.
This is not how it should be done, but at least i found a way to do it.
In the TableViewController where u have the slideOut menu do something like:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(indexPath.row == <some position> ){
let vc: AnyObject! = self.storyboard?.instantiateViewControllerWithIdentifier("YOUR_DESTINATION_IDENTIFIER")
self.showViewController(vc as! SWRevealViewController, sender: vc)
}
The one that satisfy the condition will segue with default animation, not like the slide out menu normally does.
After, in storyboard, do a normal Reveal View Controller Push controller, and as long as it doesn't satisfy the condition it will exit the slide out menu normally

Resources