Present VC modally above other VC - both touchable - ios

I want to show a VC above another VC but want both to be clickable and responsible.
I have a textfield which prints out the string behind each #-sign.
When a # is written I have a VC which pops up with a small tableview above the first VC which should later represent the users who have a name containing the printed out string.
I need the first vc to still be responsible, because currently I can't click buttons and textfields on the first VC when the second one pops up even though I can see everything ( set the background to clear).
if commentTextField.text!.contains("#"){
print("changed textField")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "suggestedUsersViewController") as UIViewController!
vc?.modalPresentationStyle = .overCurrentContext
vc?.view.backgroundColor = .clear
present(vc!, animated: true, completion: nil)
}
How I get the post behind the #- sign
let caption = commentTextField.text
let words = caption?.components(separatedBy: CharacterSet.whitespacesAndNewlines)
for var word in words! {
if word.hasPrefix("#") {
word = word.trimmingCharacters(in: CharacterSet.punctuationCharacters)
print("wort ist", word)
}
}
Currently it just pops over the first vc and then its no longer clickable and I cannot change the textfield
Pictures

present function will make the second view controller cover the whole page and you will no longer have access from screen to the view controller below the top one.
To accomplish your goal, you need to put a UITableView on a view, then keep showing or hiding the view. If you really want another view controller, you can create a containing view and have a embed segue to another view controller, like this

Related

I have a question with Swift about the correct way closing views Storyboard

I have several views and I use this code to open and close them, so I move through all of them.
let viewController = self.storyboard!.instantiateViewController(withIdentifier: "HomeViewController")
viewController.modalPresentationStyle = .fullScreen
self.present(viewController,animated: true, completion:nil)
My question is: Am I really closing them or just opening one over another wasting memory?
So after reading the wise advise I've made same chnages but I have a last question about this point,I start my app int View1, and later have to move to View2 and from there to View 3. When I’ve realized that when I’m in View 3, I have open View1, View2 and of course View 3 so to fix it when I jump from View1 to View2 , firstly I close View1 with pop and later open View2 with pop. And when I want to return to View3 I use
To move from View1 to View2
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(identifier: "View2")
self.navigationController?.popViewController(animated: true)
self.navigationController?.pushViewController(viewController, animated: true)
}
To return to View3 to View1 I use:
self.navigationController?.popToRootViewController(animated: true)
Is it correct to do a pop and a push in the same View ?
I think you're confusing yourself and getting worried over the idea that "Do I have two views open at the same time?"
This is a very common way to use a Navigation Controller:
The "Go Next" buttons push the next controller onto the navigation "stack." You automatically get a "< Back" button on the navigation bar. If your controllers have Titles, the word "Back" will be replaced with the previous controller's Title.
So, at each "step" the user can:
tap "Go Next" to go to the next "step"
tap "Back" to go back one step
If I want to let the user go "Back to Start" ... I can, for example, add a button that would call navigationController?.popToRootViewController(animated: true)
You don't need to worry about having "multiple views open." This is how Navigation Controllers work.

Accessibility Focus order after ViewController dismiss goes to the first element unintentionally

I have UIView, on which I have few UI accessibility elements (all have attribute isAccessibilityElement = true) and focus order is as below:
back button (image)
label
label
label
label with accessibilityTraits = .button
Upon clicking on element #5 (label), I transition to the new ViewController using below code:
let storyboard = UIStoryboard(name: "Sheet", bundle: nil)
guard let viewController = storyboard.instantiateViewController(withIdentifier: "Sheet") as? SheetViewController else {
return
}
On the Sheet ViewController I have some buttons which perform different actions ie. copy text to the Clipboard. Once action is tapped I run function to dismiss Sheet View Controller and within competition handler I call mainVC.setAccessibilityFocus() function which forces accessibility focus on element #5 of my UIView.
self.dismiss(animated: true, completion: {
//some more code here
mainVC.setAccessibilityFocus()
})
Function within UIVIew:
func setAccessibilityFocus() {
UIAccessibility.post(notification: UIAccessibility.Notification.screenChanged, argument: my5thElement)
}
Expected behaviour is for the accessibility focus to go onto my 5th element (label) on the UIView. However no matter what I try, focus always goes onto first accessibility element of the UIView which is back button (#1 element).
Can anyone please advice what is the best practise in terms of the accessibility focus order in this scenario and how to force focus on the different element rather than the first one?

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.

swift3 how to show navigation viewcontroller

I would like to open the specific view from the notification widget.
normally other answers are create new view..(let viewcontroller = ... )
so If you continue to call, continue use memory..
So, I want to open viewA, which is already opened in my app, and then move to viewB.
My application structure is basically a viewA when the application is launched.
What I think is that instead of creating a new viewA, I want to move to viewB using the navigation.push from the already existing viewA.
The way to check whether a particular page already exists, how to show that page at the top , and how to navigation.push is work.
now i'm using this code to open viewA from Appdelegate
let MainView: Main_View_List_ = mainStoryboard.instantiateViewController(withIdentifier: "Main_List_View") as! Main_View_List_
let nav = UINavigationontroller.init(rootViewController: MainView)
UIApplication.topViewController()?.present(nav, animated: true, completion: nil)
Assuming you have access to the navigation controller, you'll want to do something like this to pop back to viewA:
for viewController in nav.viewControllers {
if viewController is ViewAClass {
viewController.pushViewBFlag = true
nav.popToViewController(viewController, animated: true)
return
}
}
Once you get back to viewA, you can check for pushViewBFlag and create and push viewB.
Alternately, since it seems that you are setting viewA as the root of your navigation controller, you could do: nav.popToRootViewControllerAnimated(true) to get back to viewA. You would need to then handle pushing viewB from viewA.

How can I segue or pop back to the second scene of the first tab in a tabbed app, from a scene on another tab?

I have a storyboard set up with a tab bar controller and three tabs. Each tab has a navigation controller. The first tab has three scenes. There is a button (log out) in a view on the third tab that I would like to segue to the second scene on the first tab (corresponding to the log in view controller and connected to the first scene via Show(e.g., Push).
Here is what I've tried:
self.tabBarController?.selectedIndex = 0
This works, insofar as I get back to the first tab's initial scene after tapping the UIButton. But since I want to get to the second scene, this is not a complete solution. I think the solution may be along the lines of:
self.tabBarController?.selectedViewController = LoginViewController()
or
self.tabBarController?.setViewControllers(self.LoginViewController, animated: true)
But I do not want to create another instance of a view controller.
Can I still use .selectedIndex to implement a solution?
A simple solution u can try is
1. Set a Global variable (i.e in App Delegate) name as isLogoutClick of type boolean.
2. While you are on third tab and click on logout button then make the global variable "isLogoutClick" as true.
3.and then navigate to first tab (1st scene) and on viewDidLoad just check the condition that
if(appDelegate.isLogoutClick)
{
push your view to next scene.
}
4. make false the value of isLogoutClick.
5. make sure at initially the value of isLogoutClick is false.
try this might it will help you.
After setting selectedIndex to 0, perform the segue you want (in this example, "loginSegue"). You can name your segue in the storyboard if you haven't already.
tabBarController?.selectedIndex = 0
if let someViewController = tabBarController?.viewControllers?[0] as? SomeViewController {
someViewController.performSegueWithIdentifier("loginSegue", sender: nil)
}
I'm not sure if this works for tabBarController because I've used this for my navigationController but should work the same.
if let tab = self.tabBarController?.viewControllers {
if let index = find(tab.map { $0 is LoginViewController }, true) {
let destination = tab[index] as LoginViewController
tabBarController?.presentViewController(destination, animated: true, completion: nil)
}
}
With a navigationController I would use popToViewController but I'm not sure how the tabBarController exactly works

Resources