CNContactViewController for unknowncontact on tap of "Add to Existing Contact" present a view controller. When user selects cancel Navigation bar of CNContactViewController disappears and now there is no way to go back.
There might be better ways to approach this, but this worked for me. Fixed by setting the left bar button item of the navigation bar of my instance of CNContactViewController to a new instance of the cancel button that dismisses the presented CNContactViewController. In code:
let contactVC = CNContactViewController(forUnknownContact: newContact)
contactVC.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self, action: #selector(cancelAction))
I then call present and pass in contactVC. Then in cancelAction I called the dismiss function and it worked!
Related
I have a ViewController that need to display in two places.
In first place, the VC need to present and dismiss using a cancel button in its navigation bar.
In second place, the VC need to push to a navigation stack(its presented modally too) and cannot close (user have to use the back button in navigation stack).
I can display the VC in both places correctly but cannot use the close button properly. When I add the cancel bar button item to the VC, it appears in both scenarios.
How can I show the cancel button when the VC is presented and hide it when the VC is pushed?
Using isBeingPresented you can manage your cancel button,
if self.isBeingPresented {
debugPrint("Controller is Presented")
} else {
debugPrint("Controller is Pushed")
}
My app's root is a UITabBarController with 5 sections, each of them contains a UINavigationController.
I also want to add a chat feature in the app, that could be accessed with a rightBarButton present in every navigation bar of the app. I would like it to show a chat UIViewController on the screen, unselecting the currently selected tab bar item and without losing the navigation state of the five navigation controllers, even the one that was previously selected before tapping the chat button. What would be my best bet to do it?
Thanks for your help/ideas.
Step 1: In your storyboard add a ChatViewController
- Embed your ChatViewController in Navigation View Controller if you wanna have a navigation bar. Add a close BarButtonItem in your ChatViewController.
Step 2: Create a close Action in your ChatViewController and binding with BarButtonItem in the StoryBoard.
#IBAction func CloseAction(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
Step 3:
In storyboard, select the Navigation Controllers with the rightBarButton and choose Present Modally and connect to Navigation Controller of the ChatViewController.
You can go to the ChatViewController without losing the navigation state of any navigation controller.
I have an inputAccessoryView for a chat app that always remains visible and docked at the bottom of the screen for text input similar to most messaging apps.
When I present an alertController with actionSheet style, the inputAccessoryView animates down off screen as the alert is presented and then back up again when the alert is dismissed. This in turn scrolls my tableView and is undesirable.
This is happening because the chat viewController is giving up firstResponder when the alert is presented.
Is there anyway to present an alertController and not give up firstResponder, or anyway to keep an inputAccessoryView docked at the bottom of the screen when it's view resignsFirstResponder?
The InputAccessoryView sits outside of your ViewController's hierarchy - it's contained in the UITextEffectsWindow whose rootViewController is a UIInputWindowController. Similarly the keyboard is contained in UIRemoteKeyboardWindow and its own UIInputWindowController.
So, if we present the alert from the topmost window or higher (UITextEffectsWindow or UIRemoteKeyboardWindow), it won't resign first responder.
The simplest solution I've found is:
let topViewController = UIApplication.shared.windows.last!.rootViewController!
topViewController.present(alert, animated: true, completion: nil)
Ideally you would safely handle those optionals. A potentially better solution (I've seen some console errors from the previous solution) would be to create a new UIWindow with a higher WindowLevel, make it the key window and visible, and present the alert from there.
Thanks to #Corey W. (give votes to him) we have a solution for this issue. Safer way in Swift 5:
// Instantiate AlertController
let actionSheet = UIAlertController(title: title,
message: "Comment options",
preferredStyle: .actionSheet)
// Add actions
actionSheet.addAction(UIAlertAction(title: "Edit",
style: .default,
handler: { (_: UIAlertAction) in
self.showEditingView(withCommentId: commentId, withCommentText: commentText)
}))
// Present AlertController
if let lastApplicationWindow = UIApplication.shared.windows.last,
let rootViewController = lastApplicationWindow.rootViewController {
rootViewController.present(actionSheet, animated: true, completion: nil)
}
For those looking the Objective-C equivalent of Corey's answer:
UIViewController *objViewController = [UIApplication sharedApplication].windows.lastObject.rootViewController;
[objViewController presentViewController:view animated:YES completion:nil];
I am creating an iOS app which consists of 2 storyboards.
This is the second one:
I am targeting iOS 7 so I cant use storyboard references. Switch between storyboards is handled programmatically
Using this code:
let viewController:UIViewController = UIStoryboard(name: "Warnings", bundle: nil).instantiateViewControllerWithIdentifier("WarningsInitialView") as UIViewController
self.presentViewController(viewController, animated: true, completion: nil)
I can get to the second storyboard using this. However as you can see second storyboard consists of Tab Controller and I want (on both tabs) back button which will point to the main (previous) storyboard. How should I achieve this?
I have tried using this code:
AvalanchesBackButton.leftBarButtonItem = UIBarButtonItem (title: "< Spät", style: UIBarButtonItemStyle.Plain, target: self, action: "backButtonClicked")
I will be able to achieve what I want by using different view controllers for both views and hardcoding it. But is there a way to do it more cleanly? Like implement a back button on container Tab Controller which will point to previous storyboard?
Thanks in advance
Is your previous ViewController embedded into a Navigation controller? because "pushing" the view controller automatically adds the back button.
self.navigationController?.pushViewController(viewController: UIViewController, animated: Bool)
I want to set the common Bar Button Item on the right of the Navigation Bar, it should be display on all screens managed by Navigation Controller and it calls the same action.
Just for example, in Master Detail Application template, there is "addButton" on the right of the Navigation Bar, I want to display it on DetailViewController as well (it won't be work because action is missing though).
I have created a subclass of UINavigationController, in which I can change something like Navigation Bar color, but I can't set Bar Button Items. I can set Bar Button Items in each screen's ViewController so that I have to duplicate action for each screen.
Also I've tried to create a subclass of UINavigationBar, but I don't know if I can add Bar Button Item on it.
How to set common Bar Button Item on Navigation Bar?
Thanks in advance.
Another easy way to do instead of creating an extension
implement UINavigationControllerDelegate in root view controller
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
let backBarButton = UIBarButtonItem.init(title: "HINIBO", style: .Plain, target: self, action: Selector("menuButtonAction:"))
viewController.navigationItem.rightBarButtonItem = backBarButton
}
You can use category to approach it. Let's say UIViewController+NavigationBar category
1.Create a category
2.Add a method, -(void)setNavigationBarItem method (in this case) in .h file.
3.implement the method in .m file to deal with the set Bar Button Items stuff.
- (void)setNavigationBarItem
{
UIBarButtonItem *searchItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:#selector(something)];
self.navigationItem.rightBarButtonItem = searchItem;
}
4.In which viewController you want the NavigationBarItem, import the category header and call [self setNavigationBarItem] method.