Swift - Assign View Controllers dynamically to the Tab bar - swift

My App is all based on API data. I am able to create a tab bar controller from api data but just ended up in confusion on how to create view controllers for each tab bar item dynamically. Here is the code so far -
for i in 0..<navgTitle.count {
print(navgTitle.count)
controller1 = WeatherViewController()
controller1.title = navgTitle[i]
controller1.tabBarItem.title = navgTitle[i]
controller1.tabBarItem.image = UIImage(named: "AppIcon")?.withRenderingMode(.alwaysOriginal)
array1.append(controller1)
}
print(array1)
tt.viewControllers = array1
self.view.addSubview(tt.view)
self.tabBarControllr.moreNavigationController.show(tt, sender: self)
tt.customizableViewControllers = []
}
In the above code, in the 'for' loop i want to create view controllers for each tab bar item (say 'HomeViewController', WeatherViewController' etc). I do not know how to do that and is it really possible? I can not create view controller classes manually because each app has their own tab bar items to show. Please suggest a way to do this..Thanks in Advance

Related

Search bar behavior inside Navigation Bar is inconsistent in iOS 13

I am trying to include search bar inside the navigation bar through navigation item of the view controller.
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationItem.title = "Sticky Section Headers"
self.edgesForExtendedLayout = .all
self.extendedLayoutIncludesOpaqueBars = true
self.navigationItem.searchController = UISearchController()
setUpNavBarAppearance()
}
This view controller has a collection view and when user taps on a cell in the collection view, i am pushing the a new instance of same view controller(demo purposes) on to the navigation stack..
The behavior for the search controller has been inconsistent between the two view controllers. For the first/root view controller, the search bar shows up by default, but for the second view controller that is pushed on to the navigation controller, the search is hidden by default until user scrolls down.. I would like keep the search appearance behavior consistent across both the screens..
I am aware of the hidesSearchBarWhenScrolling setting to false would keep the search bar visible all the time, but i want to hide the search bar while user is scrolling.
Is there anyway to get the consistent behavior?
Here is the gist file, if you like to try the code:
https://gist.github.com/prasadpamidi/829e636d4697fda025bb0795ee81e355
Appreciate any help.

Swift iOS Dynamic Tab bar from json response

I'm new to iOS/Swift. My application is using a json data and I have to create tab bar using the json response. I mean, I get Array of Title from json and I have to create tab bar items based on that array. The Array data/count may change and the app should display the tab bar accordingly. I am trying to create the tab bar programatically without storyboards (as this is huge tab bar)
So far, I have tried the below code -
func tabBarCustom() {
let tt = UITabBarController()
var array1 = [UIViewController]()
var controller1 = UIViewController()
for i in 0..<navgTitle.count {
controller1 = UIViewController(nibName: "WeatherViewController", bundle: nil)
controller1.title = navgTitle[i]
controller1.tabBarItem = UITabBarItem(title: navgTitle[i], image: .none, tag: 1)
array1.append(controller1)
}
print(array1)
tt.viewControllers = array1
self.view.addSubview(tt.view)
}
The above code is failing saying - Could not load NIB in bundle: 'NSBundle' with name 'WeatherViewController'
I am not sure how to create multiple view controllers automatically using the title array, taking title as name of the view controller. is this possible? and how to loop in the array to create view controllers for each tab bar item
please help.Thank you
Are you using nibs? If so, your project can't find the nib file, and you should check out this: Could not load NIB in bundle: 'NSBundle'. Or are you using Storyboard? If you are trying to initialize from the storyboard, you'll do something like this:
let vc = sb.instantiateViewController(withIdentifier: "WeatherViewController")
(just be sure to add WeatherViewController as the view controller's identifier).
OR are you using code? If you are trying to create your view controller from code, you simply need to do WeatherViewController().
As for the tab bar, you're in the right direction it's just that creating the view controller is failing.

How to get the navigation bar to show large title upon a segue back?

I have a tab bar app where one of the views is a UITableViewController containing static cells as content with 1 section and 1 row.
I want the Large Title to be set to "Always," so I made the selection on the storyboard and the title was large on the simulator. Now when the user taps "Start Chat," the app will segue to the Virtual Assistant View Controller, where the Large Title is set to "Never" on the storyboard. Now the problem is that when the user segues back to the previous view controller with the "Start Chat" table view cell, the title is not large anymore.
It is interesting that when I set the table view to be scrollable, the title becomes large again upon dragging down the table view. I made sure the navigation bar on the Navigation Controller storyboard is checked with the "Prefers Large Titles." I am using Xcode 11, and this was not a problem when using Xcode 10.
I tried creating a custom class for the view with the start chat button and this code did not work in making the title large from a segue back:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
What else could I do? Any help will be greatly appreciated!
I'd use willMove(toParent:) to change the title back before the segue is performed.
override func willMove(toParent parent: UIViewController?) {
navigationController?.navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
}
Set the properties when setting up the UINavigationController, before presenting it. If you already presented the navigation controller, try doing this to force-update the navigation bar:
navigationController?.navigationItem.prompt = ""
navigationController?.navigationItem.prompt = nil
I took this workaround from this question.
In your particular case, it would be better to subclass the navigation controller and set those properties in its viewDidLoad method, so its properties (largeTitleDisplayMode and prefersLargeTitles) are set in a self-contained code.

How to trigger a segue from a tab bar item to another by clicking a button?

I am trying to create a Tab View Item inside a Tab View Controller which switches to the other Tab View Items not only by tapping on the item in the Tab Bar but also via a button which I create myself.
From one of your VCs the tab bar controller, you can access the tab bar controller by accessing parent. If your VC is also embedded in a navigation controller, you need to access parent.parent.
// assuming "self" is embedded in a navigation controller
if let tabBarController = self.parent?.parent as? UITabBarController {
}
After you have the tab bar controller, you can set its selectedIndex to go to whichever tab you want:
tabBarController.selectedIndex = 1 // second tab
From the docs of selectedIndex:
...Setting this property changes the selected view controller to the one at the designated index in the viewControllers array...

Swift 3 - How do I insert TableViewCells from another view?

I am using Swift 3, Xcode 8.2.
I am trying to figure out how to insert cells into my table view from another tab of my tabbed view controller.
MyTableView
class MyTableView: UITableViewController {
var items = ["Item 1", "Item 2", "Item 3"]
...
func insertCell() {
items.append("Item \(items.count + 1)")
tableView.reloadData()
}
If I create a bar button item on that table view page, I can successfully insert items, no problem. It's when I try to trigger it from another view controller that nothing happens.
Another Tab
#IBAction func triggerInsert(_ sender: Any) {
//MyTableView().insertCell() // this doesn't work
//MyTableView().items.append("Item") // these two lines don't work either
//MyTableView().tableView.reloadData()
// also tried setting a boolean in here to be read from MyTableView but that didn't work either
}
I'm not quite sure what the "correct" way to do this is. Any help would be greatly appreciated.
The problem is this expression you keep trying to use:
MyTableView()
That creates a completely new and separate table view controller. But that obviously is not what you want to do. You want to talk to the existing table view controller, the one that is, as you say, another tab in the tab bar controller.
For example, if MyTableView is the first tab and OtherViewController is the second tab, then OtherViewController might say:
self.tabBarController!.viewControllers![0] as! MyTableView
...as a way of getting a reference to the existing table view controller.