When I search , Button action in Cell don't work - swift

In my app, I used XLPagerTabStrip! library.
[HomeViewController like this 1
In my HomeView controller, I have a 3 child view that uses same searchBar in NavigationController.
In my ChildOneController, I have a tableView that list videos.
I have a button in TableViewCell. When I click this button, pushviewController. But when i searched and click this button push don't work.
here is my code :
func joinBtnDelegate(at index: IndexPath) {
if let jlist = self.joinAllAllowedInnoList , !jlist.isEmpty{
Dataholder.sharedInstance().selectedJoin = jlist[index.row]
let vc = self.storyboard?.instantiateViewController(withIdentifier: "PickVideoViewController") as! PickVideoViewController
self.navigationController?.pushViewController(vc, animated: true)
}
}
any advice ?

Make sure that navigationController should not be nil in below line of code.
self.navigationController?.pushViewController(vc, animated: true)

Related

using pushViewController in containerView Not work

I have created containerView which contain tableViewController.
The main issue, when user click on information, tableViewController must show the information which user clicked.
it show the information when I use present(<#T##UIViewController#>, animated: <#T##Bool#>, completion: <#T##(() -> Void)?#>)
but doesnt work if I call self.navigationController?.pushViewController
the main issue is when I make vc.info = info it doesnt work, the info has value but using injection the value in another class is nil.
Here is my code:
func showLoginDetailsOnIpad(encryptedDataBase: info) {
self.view.addSubview(loginContainer)
let mainStoryboard : UIStoryboard?
mainStoryboard = UIStoryboard(name: "StoryboardiPad", bundle: nil)
let vc = mainStoryboard!.instantiateViewController(withIdentifier: "tableVC") as! tableVC
vc.info = info
vc.showingLoginInfo = true
vc.modalPresentationStyle = .automatic
self.navigationController?.pushViewController(vc, animated: true)
}
Explanation
You mentioned the use of a containerView. The table controller being displayed inside the containerView, doesn't automatically get a reference to the nearest navigationController.
So in this line: self.navigationController?.pushViewController(vc, animated: true)
self.navigationController might actually be nil. You can confirm this by printing its value before running the push method like so:
print(self.navigationController) // See if this prints nil.
self.navigationController?.pushViewController(vc, animated: true)
Fixes
To fix the issue, I suggest to pass a reference to the parent controller's navigationController to the child controller - through the embed segue.
In your parent controller, you can use this code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? UITableViewController{
destination.navigationController = self.navigationController
}
}
And in your table view controller, leave the code as is.

Remove a ViewController from navigationStack and add a new instance of it

I have a SongNamesViewController with navigationController embedded. When a song is chosen from a list I open PlaySongViewController and add to the navigationController using following function:
func openPlaySongViewController() {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let playSongViewController = storyBoard.instantiateViewController(withIdentifier: "playSongViewController")
self.navigationController?.pushViewController(playSongViewController, animated: true)
}
Now, a message arrives via remote push-notification. The user taps on the push-notification icon and then I display the song using "openPlaySongViewController()" function. If another push-notification comes and then I display another PlaySongViewController on top of existing PlaySongViewController.
Current flow: (NavigationController)->SongNamesViewController>PlaySongViewController->PlaySongViewController
How do I remove the existing PlaySongViewController that is on the navigationController before adding a new instance of PlaySongViewController?
I tried the following but the PlaySongViewController that is on navigationController does not go away.
for viewController in self.navigationController!.viewControllers {
if viewController.isKind(of: PlaySongViewController.self) {
viewController.removeFromParent()
}
}
topViewController returns what is on top of the navigation stack. So you should pop it if needed.
func removeLastControllerIfNeeded() {
guard navigationController?.topViewController is PlaySongViewController else { return }
navigationController?.popViewController(animated: true)
}

Change ViewController from Tabbar

I have a UITabBarController with 3 tabs and a SettingsVC where you can choose the appearance of MainVC (There are 2 different ViewControllers which based on what user prefers should be shown as the MainVC).
I made the application and it works but it's really buggy, cause I was just pushing the ViewControllers on top of each other, and in some certain conditions you see bugs while switching tabs.
Main.storyboard
Here is some part of my code(after trying a lot of stuff) which changes the VC's based on UserDefaults
CheckSettingsStatus.swift
//
// Check for Double Column Settings and navigate to Double Column VC
//
func checkMainVCViewStatusAndNavigateAcordingly(){
if UserDefaults.standard.integer(forKey: KEY_MAIN_VC_VIEW) == 1{
//let appDel = UIApplication.shared.delegate as! AppDelegate
//appDel.goToDoubleMainVC()
let mainVC = storyboard?.instantiateViewController(withIdentifier: "DoubleColumnMainVC") as! DoubleColumnMainVC
self.navigationController?.viewControllers[0] = mainVC
//navigationController?.pushViewController(mainVC, animated: false)
var navigationArray = self.navigationController?.viewControllers
print("Number of VCs = \(String(describing: navigationArray?.count))")
if navigationArray?.count == nil{
self.navigationController?.pushViewController(mainVC, animated: false)
}else{
self.navigationController?.popToRootViewController(animated: false)
}
// self.navigationController?.viewControllers = navigationArray!
}
}
//
// same as function above but goes to MainVC
//
func checkDoubleColumnMainVCViewStatusAndNavigateAcordingly(){
if UserDefaults.standard.integer(forKey: KEY_MAIN_VC_VIEW) == 0{
// let appDel = UIApplication.shared.delegate as! AppDelegate
// appDel.goToMainVC()
let mainVC = storyboard?.instantiateViewController(withIdentifier: "MainVC") as! MainVC
self.navigationController?.viewControllers[0] = mainVC
var navigationArray = self.navigationController?.viewControllers
print("Number of VCs = \(String(describing: navigationArray?.count))")
if navigationArray?.count == nil{
navigationController?.pushViewController(mainVC, animated: false)
}else{
self.navigationController?.popToRootViewController(animated: false)
}
// self.navigationController?.viewControllers = navigationArray!
}
}
With this in ViewWillAppear of both this Controllers I call these functions to switch accordingly.
Any ideas what I'm doing wrong? Can I push controllers from UITabBarController and not NavigationController? something like:
tabBarController.pushViewController(mainVC, animated: false)
instead of:
navigationController.pushViewController(mainVC, animated: false)
Thank you in advance
UPDATE:
In my best case when everything works nicely, on first launch of the app (to the second mainVC) the Buttons in NavBar doesn't work.
EDIT:
I just realised that the NavigationBar that I'm seeing above my SecondMainVC is the NavigationBar from MainVC, that is why the buttons are not working. how is that possible?
I faced same issue while trying to develop a tab bar controller in storyboard , for this reason I found that the best way is to implement it by code.
so you can make your code look like this :
1) create a a sub class of UITabController and let it conform to UITabBarControllerDelegate
class TabBarVC: UITabBarController , UITabBarControllerDelegate {
2)then write this method in your class to initialize the tabs in your project:
private func settingUpTabBarAndInitializingViewControllers(){
//self delagting
self.delegate = self
//home tab
let homeStoryboard = UIStoryboard(name: Constants.StoryBoards.homeStoryboard, bundle: nil)
let homeVC = homeStoryboard.instantiateViewController(withIdentifier: Constants.ControllersIDs.homeScreen) as! HomeVC
// shop tab
let shopStoybaord = UIStoryboard(name: Constants.StoryBoards.shopStoryboard, bundle: nil)
let shopVC = shopStoybaord.instantiateViewController(withIdentifier: Constants.ControllersIDs.shopScreen) as! ShopVC
//offers tab
let offersStoryboard = UIStoryboard(name: Constants.StoryBoards.offersStoryboard, bundle: nil)
let offersVC = offersStoryboard.instantiateViewController(withIdentifier: Constants.ControllersIDs.offersScreen) as! OffersVC
//more tab
let moreStoryboard = UIStoryboard(name: Constants.StoryBoards.MoreScreenStoryboard, bundle: nil)
let moreVC = moreStoryboard.instantiateViewController(withIdentifier: Constants.ControllersIDs.moreVCScreen) as! MoreOptionsTVC
//setting VCs
self.viewControllers = [homeVC , shopVC , offersVC , moreVC]
//setting buttons
//buttons images
let homeImage = UIImage(named: "TabHome")
let shopImage = UIImage(named : "TabShop")
let offerImage = UIImage(named: "TabOffers")
let moreImage = UIImage(named: "TabMenu")
// buttons shakhsiyan
let homeButton = UITabBarItem(title: homeText, image: homeImage, selectedImage: homeTappedImage)
let shopButton = UITabBarItem(title: shopText, image: shopImage, selectedImage: shopTappedImage)
let offersButton = UITabBarItem(title: offersText, image: offerImage, selectedImage: offersTappedImage)
let moreButton = UITabBarItem(title: moreText, image: moreImage, selectedImage: moreTappedImage)
homeVC.tabBarItem = homeButton
shopVC.tabBarItem = shopButton
offersVC.tabBarItem = offersButton
moreVC.tabBarItem = moreButton
}
P.S. you can add tabs as much as you want and while scrolling in them you wont face any bug,
make sure to have only one navigation controller before your tab bar controller.
Check this hope it helps
Ok you can create a DEMO to see how thing works.After that you can implement it in your project.I know it may not look good to you but read it once and see image attached i am sure will get your answer.
1.I have created two UIViewControllers with the UITabBarController.
2.I have created class ItemFirstVC,ItemTwoVC and assigned to UIViewControllers in storyboard
3.Each controller is embedded in UINavigationController
4.Create a custom class of UITabBarController
5.Assign it to UITabBarController in storyboard
6.Now Each UIViewController has a button named as Firs Button,Second Button
7.From each button i have connected Action Segue to one more controller as you can see in image.
8.Now i have created a third UIViewController which is separate from UITabBarController.
9.Now we will load that Third UIViewController in UITabBarController
10.Create one more class ItemThirdVC and assign it to third UIViewController.
11.It also has a button named as third button action segued to one more UIViewController
12.Now switch to custom class of UITabBarContoller
// variable required to see work in action
var count = 0
class CustomTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// remember to assign delegate
delegate = self
}
// this delegate indicates whether this tab should be selected or not
extension CustomTabBarController : UITabBarControllerDelegate{
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
// switch to UIViewController tabs multiple times
count = count + 1
if(count == 5){
// when count reaches 5 a new controller will load
let navigationController = viewController as? UINavigationController
guard navigationController != nil else {return true}
let viewController = storyboard?.instantiateViewController(withIdentifier: "ItemThreeVC")
guard let vc = viewController else {return true}
navigationController?.setViewControllers([vc], animated: false)
}
return true
}
}

Can one uitableviewcell segue 2 view?

i wanted to ask, if i got one uitableviewcell, i need to do checking to meet the condition then only perform to different segue to different view, how to do it? Example like:
if subCat[indexPath.row] == ""{
performSegueWithIdentifier("A", sender: self)
}else{
performSegueWithIdentifier("B", sender: self)
}
How to do it? And how should i connect it with segue at the storyboard?
Even you can do by giving storyboard identifier "A" to viewController 1 and "B" to viewController 2 and push you controller if using navigation otherwise simply present the viewcontroller.
if subCat[indexPath.row] == "" {
let viewController1 = storyboard.instantiateViewControllerWithIdentifier("A") as! ViewController1
// if navigation controller used.
self.navigationController?.pushViewController(viewController1, animated: true)
// if navigation controller not used.
// self.presentViewController(viewController1, animated: true, completion: nil)
}else{
let viewController2 = storyboard.instantiateViewControllerWithIdentifier("B") as! ViewController2
// if navigation controller used.
self.navigationController?.pushViewController(viewController2, animated: true)
// if navigation controller not used.
// self.presentViewController(viewController2, animated: true, completion: nil)
}

iOS change tab programmatically

I'm developing an iOS application with a tab bar and navigation. When I press a button in the first tab I want it to load the second tab with a navigation controller and push the next view. Can someone help with this?
You can programatically select tab by
self.tabBarController.selectedIndex=1;
The button in the first tab sends a message to the tab controller, telling it to select the second tab. Then you send a message to the rootView of the second tab, which is a navigation controller, and tell it to push such and such an object that you create in the class with the first button.
Set selectedViewController:
self.tabBarController.selectedViewController = viewControllerYouWant;
For example,
self.tabBarController.selectedViewController
= [self.tabBarController.viewControllers objectAtIndex:2];
Here is a Swift solution for anyone that needs it. I had to do the same thing just go from a nested view controller in tab 2 to another nested view controller in tab 4. Here is how I achieved that:
func goToHelpViewController(){
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let desiredIndex:Int = 3
self.tabBarController?.selectedIndex = desiredIndex
let settingsStoryBoard = UIStoryboard(name: "SettingsSection", bundle: nil)
let helpViewController = settingsStoryBoard.instantiateViewControllerWithIdentifier("HelpViewController") as! HelpViewController
let settingsRootNavigationController = self.tabBarController?.viewControllers![desiredIndex] as! UINavigationController
settingsRootNavigationController.popToRootViewControllerAnimated(false)
settingsRootNavigationController.pushViewController(helpViewController, animated: true)
})
}
Swift 3.0
func goToHelpViewController(){
DispatchQueue.main.async(execute: { () -> Void in
let desiredIndex:Int = 1
self.tabBarController?.selectedIndex = desiredIndex
let settingsStoryBoard = UIStoryboard(name: "SettingsSection", bundle: nil)
let helpViewController = settingsStoryBoard.instantiateViewController(withIdentifier: "HelpViewController") as! HelpViewController
let settingsRootNavigationController = self.tabBarController?.viewControllers![desiredIndex] as! UINavigationController
settingsRootNavigationController.popToRootViewController(animated: false)
settingsRootNavigationController.pushViewController(helpViewController, animated: true)
})
}