Black screen after presenting model view controller in current context from tab controller - ios

I'm creating a Popup error message for my own app. I have followed a tutorial in Youtube. As my app is a tab bar app when Popup, comes up and a user presses another tab and then get back to that specific tab the background is changed !!!! any Idea what is happening here?
1. This is when the popUp comes up
2.This one is when has change the tab and then came back to that specific tab
3.This is the last state when the user close the popup after they changed the tab
none of these bugs happens if the user closes the pop up at the beginning!
let next = self.storyboard?.instantiateViewController(withIdentifier: "ErrorVC")
self.present(next!, animated: true, completion: nil)
and this is the code I have used in my page to show the pop when it meets the conditions !!!
I have 2 viewController and second one is the pop up.

Set definesPresentationContext property to true of UIViewController in first viewController where you're displaying pop-view
override func viewDidLoad() {
super.viewDidLoad()
definesPresentationContext = true
}

Related

How can I disable some of the tabs of the moreNavigationController of my UITabBarController?

I'm using XCode 13.0, Swift 5.5 and Storyboard. This is a mobile app for iPhone with iOS 15.
I have altogether 7 tabs, all of them with icons. I have 4 tabs and a "More" tab in the tab bar of my app.
3 additional tabs show up after the user clicks on the "More" tab. I'd like the first 2 of these additional tabs to be disabled. They need to be grey coloured and when the user clicks on any of these 2, I'd like to app to do nothing (not to show any page, not to navigate anywhere). I'm using the original UITabBarController and moreNavigationController defined by Apple, I didn't subclass any of them.
On my storyboard I added 2 UIViewControllers to these 2 disabled tabs, but I set them disabled this way:
This didn't work at all. When the user clicks on the 2 disabled tabs, they show 2 empty ViewControllers. I'd expect them not to show anything.
I also tried accessing the moreNavigationController's tabs from the page my UITabBarController first opens. I tried setting these 2 tabs disabled programmatically. However I didn't manage to access these 2 tabs, I only manage to access the main tabs that show up in the tab bar (I don't need to access these). How can I disable and colour grey the tabs that show up after clicking on the More tab?
let moreControllerItems = tabBarController?.moreNavigationController.toolbarItems
if let tabArray = moreControllerItems {
let tabBarItem1 = tabArray[0]
let tabBarItem2 = tabArray[1]
tabBarItem1.isEnabled = false
tabBarItem2.isEnabled = false
}`
This code doesn't work, the moreControllerItems variable is nil. The tabBarController variable isn't nil, I can access my UITabBarController from here, but it doesn't help me much.
I googled this issue lots of different ways but I couldn't find the solution. Any help would be appreciated. I really need to solve this, please write a comment if you have any idea how to solve this. Thank you!
You can disable tabBar items from TabBarController.
class TabVC: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
func disableTabBar(itemNo: Int) {
if let items = tabBar.items, itemNo < items.count {
items[itemNo].isEnabled = false
}
}
And you can access this function from
any child Viewcontroller attached to TabBarController
class MoreVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let tabBarVC = tabBarController as? TabVC {
tabBarVC.disableTabBar(itemNo: 1)
}
}
In short: You cannot disable it. If you want to disable the item in the More Viewcontroller, you have to use a custom Viewcontroller in the fifth Tab
I am explaining here why we cannot do it and what limitations we have.
Apple will show the More tab if items are more than five in the UITabBarController. And more tab holds the UINavigationController which is attached to a kind of UIMoreListController. you can check by
print moreNavigationController.viewControllers[0]
UIMoreListController is not accessible. In your case, the remaining three items are listed in the UIMoreListController. Although we can still access the Viewcontroller's tabBarItem and we can disable it. You can check by clicking the edit option.
But still, users can click on it as long as it is in the UIMoreListController. Because we are not interacting with the tabBar instead we are interacting with the items on the list. Users can't click once you move the item to any of the first four positions using the edit option in the MoreViewcontroller.

How can I push two VC but only presenting top VC

I would like to emulate contact list in ios. When one taps + button to add contact, a new view controller is presented that gives you textfields to enter contact name and additional info for saving about that contact. Once you tap Done button, the next view controller presented already seems to be embedded in a navigation controller with the button that takes you back to the contact list. I've tried code found on here but it pushes 3 view onto navigation stack
//first attempt
var controllers = navigationController?.viewControllers
controllers?.append(secondVc)
controllers?.append(thirdVC)
navigationController?.setViewControllers(controllers!, animated: true)
//second attempt
let pushVC = UIViewController()
let backVC = UIViewController()
if let navigationController = navigationController {
navigationController.pushViewController(pushVC, animated: true)
let stackCount = navigationController.viewControllers.count
let addIndex = stackCount - 1
navigationController.viewControllers.insert(backVC, atIndex: addIndex)
}
I've also tried other combinations that look cringy. Here is what I want it to look like: https://imgur.com/a/IAJ5G
This should work:
navigationController.pushViewController(secondVc, animated:false)
navigationController.pushViewController(thirdVc, animated:true)
Apple does the same by presenting a new window, with the form to create a new contact.
After making the new window as the keyWindow, they push the contact details VC on to the navigation controller on the original window. This push happens in the background, which the user is not able to witness.
You can view the same by attaching a debugger to the Contacts app.
Heres a screenshot of the view hierarchy. You will be able to see that there are no view controllers from the original window underneath the CNContactContentViewController.
When the user taps Done, the original window is restored as the keyWindow, and the contact details VC is updated to show the newly added contact.

can we programatically set to which tabar item should be displayed when a tab bar is shown?

I am working on a project which contain a tab bar. The tab bar contain 2 items named leave and Od. Both are normal viewcontroller class. They have a table view inside it(I dont mean table view controller). While clicking on a item in a table view a pop Up screen appears which have a viewcontroller swift file named as popUpviewController. This show details of item selected in table view. The problem is when i dismiss the popUpdialog i always get the selected tabBar item as the default one.Here its leave authorise.
what I did is i gave an Storyboard Id to tab Bar controller and called it from the popUp when its dismissed, like this.
let viewController:UIViewController = UIStoryboard(name:self.whichSB!, bundle: nil).instantiateViewControllerWithIdentifier("AuthoriseTabBar?") as UIViewController
self.tabBarController?.selectedIndex=2 /* DOESN'T WORK OBVIOUSLY*/
self.presentViewController(viewController, animated: false, completion: nil)
** The tab bar controller doesn't have any associated class with it.I would like to show item 1 when item1 popUp is dismissed(This works as its now the default item shown in tab bar), and item 2 when item 2 popUp is dismissed.**
Can anyone suggest a away of doing the above . and I havent used any navigation controller here, is it necessory to get tabbar.selectedindex of tab bar
You can access the tab bar, from the popup VC, like this. Just run this with the normal dismiss line as shown.
if let presentingVC = self.presentingViewController {
if let tabController = presentingVC.tabBarController {
tabController.selectedIndex = 0 // Whatever index you want to select.
}
}
self.dismiss(animated: true, completion: nil)

Right way or event to choose what view load in swift

I'm working in an app that logs in an user if there isn't another user already logged in at launch time. This way the first view to appear should be the Login View. But in the case there is a logged user already, the first view appearing should be the main menu. Im handling this with the viewWillAppear function and it's working, but I don't know if this is the correct approach or how it should be handle in this situations.
Here is my code. My first view is MainMenuVC in which I control if there is a logged user or not, then I choose if stay in main menu view or push my login view.
class MainMenuVC: UIViewController {
override func viewWillAppear(animated: Bool) {
if (UserMgr.users.count == 0){
var vc1:LoginVC = self.storyboard?.instantiateViewControllerWithIdentifier("LoginView") as LoginVC
self.navigationController?.pushViewController(vc1, animated: false)
}
else
{
//I do nothing so this view is loaded
}
}
I don't know if i should use another ViewController and implement the function loadView() to decide what view load, but the problem is make that view work with the story board and my navigation controller.
Any suggestions?
Basically you will have two different view controllers, one for the login screen (VCLogin) and one for the main menu (VCMainMenu). Now, in your AppDelegate there are methods which are called, when the app launches respectively when it appears. So, place the code checking whether a user is logged in there and make the appropriate view controller the root view controller, e.g.
let navigationController = window.rootViewController as UINavigationController
navigationController.rootViewController =
userIsLoggedIn ? mainMenuViewController : loginViewController

Swift: Buggy Navigation Bar Behavior With popViewControllerAnimated

I want to use a push segue to edit an "entry" that is otherwise added via a present modally segue. It doesn't dismiss using the normal dismissViewControllerAnimated method when pressing cancel. Because of this I had to combine the popViewControllerAnimated method at the same time, so that depending on whether they click cancel when editing an entry or adding it, it will try both.
Both are done via NSNotifcation, because of objects I need to carry back from the last viewcontroller to the first:
func cancel(notification: NSNotification){
println("Cancel Executed")
let userInfo:Dictionary<String,EntryItem!> = notification.userInfo as Dictionary<String,EntryItem!>
entry = userInfo["Object"]
tableView.reloadData()
self.navigationController?.popViewControllerAnimated(true)
dismissViewControllerAnimated(true, completion: nil)
dataModel.saveEntries()
}
The problem with this is that if I go through the segues to arrive at the third view controller (in a string of 5), I cancel, and it goes back to the entries screen, but a messed up looking navigation bar takes the place of what is supposed to be there. There's no title showing either. It has a cancel button which causes a crash if you press it.
Here's what it's supposed to look like:
Here's what the popViewControllerAnimated does to it.

Resources