When I open a calendar event in my app using EKEventViewController using the code below it correctly displays my event in a modal view.
let eventModalVC = EKEventViewController()
eventModalVC.event = myEvent
eventModalVC.allowsEditing = true
present(eventModalVC, animated: true, completion: nil)
In portrait mode (using iOS 15) I can dismiss the modal using a swipe-down gesture. However, when I change to landscape orientation, the gesture does not work, and there is no back or cancel button either (like there is for the EKEventEditViewController). I could not find any property of the view controller that would enable me to dismiss it.
So the user is either stuck or has to turn the device into portrait mode. How can I fix this?
I was hoping that the EKEventViewController offers a similar convenient and intuitive way to dismiss it in landscape view as it does in portrait view but have not had any luck.
To get the back button I now enclosed my modal view in its own navigation controller. That reveals a "Done" button (as well as a delete button). Neither button dismisses the view. That can be done by implementing EKEventViewDelegate in the parent view controller.
let eventModalVC = EKEventViewController()
eventModalVC.event = myEvent
eventModalVC.allowsEditing = true
let nc = UINavigationController(rootViewController: eventModalVC)
eventModalVC.delegate = self
present(nc, animated: true, completion: nil)
...
// EKEventViewDelegate
func eventViewController(_ controller: EKEventViewController, didCompleteWith action: EKEventViewAction) {
if action == .done {
controller.dismiss(animated: true)
}
// handle deletion as well if needed
}
Related
In my viewDidLoad, I have the below code to hide the back button. However, when implemented, this disables the back button of further View Controllers in the chain of which I segue to. I'm not sure, but this may be to do with how I structure my app (please see image - note that the Navigation Controller on the far left is connected to a Tab Bar Controller).
// Removes back button
self.tabBarController?.navigationItem.hidesBackButton = true
self.tabBarController?.navigationItem.setHidesBackButton(true, animated: false)
self.tabBarController?.navigationItem.leftBarButtonItem = nil
I've also tried the following code, but this didn't work as well.
self.navigationItem.leftBarButtonItem = nil
self.navigationController?.navigationItem.leftBarButtonItem = nil
navigationItem.setLeftBarButton(nil, animated: false)
self.navigationItem.setLeftBarButton(nil, animated: false)
self.tabBarController?.navigationItem.leftBarButtonItem = nil
self.tabBarController?.navigationItem.setLeftBarButton(nil, animated: false)
self.navigationController?.navigationBar.topItem?.leftBarButtonItem = nil
If you only want to hide the back button on the current screen you should only clear the leftBarButtonItem. If you hide the backBarButtonItem too that will be applied to the next screen's navigationItem. Does this help?
try
self.parent?.navigationItem.setHidesBackButton(true, animated: false)
sometimes the viewController does not recognize it's navigation Controller without self.parent
Pretty new to Swift so forgive my ignorance. I have a navigation controller which is linked to a View controller called Profile. In ProfileViewController.swift I have it to where it opens up another view controller if no profile exists. Here's an example of what I have at the moment:
// ProfileViewController.swift
var profileExists = 0
override func viewDidLoad() {
super.viewDidLoad()
// Check if user has a profile. If so, go to view page; otherwise, bring up new profile view.
if profileExists != 1 {
// Create new profile page.
if let vc = storyboard?.instantiateViewController(withIdentifier: "EditProfileController") as? EditProfileViewController {
present(vc, animated: true, completion: nil)
}
print("Need to create new profile.")
}
//Scroll view size
ScrollView.contentSize.height = 1000
}
// Cancel button was pressed.
#IBAction func unwindToHomeScreen(segue:UIStoryboardSegue) {
}
What I'm trying to do is link my "Cancel" bar button in the "EditProfile" view controller to dismiss it if the user clicks cancel. However, trying to replicate an example from a tutorial isn't working. I can't control + drag the Cancel button to the Exit button and use a defined unwind segue. Not quite sure why just yet.
Any ideas on the best way I should be trying to dismiss this view controller?
Simple call
self.dismiss(animated: true, completion: nil)
I am trying to create a pop over and when I present the view controller, the background is always solid black and the size is full screen.
I can't seem to figure out what's wrong and here is the code that I have
#IBAction func distancePopOver( sender : UIBarButtonItem){
//a UIViewController that I created in the storyboard
let controller = storyboard!.instantiateViewControllerWithIdentifier("distancePopOver")
controller.modalPresentationStyle= UIModalPresentationSTyle.PopOver
controller.preferredContentSize = CGSizeMake(200,30)
self.presentViewController(controller, animated: true, completion: nil)
//Configure the Popover presentation controller
let popController = (controller.popoverPresentationController)!
popController.permittedArrowDirections = UIPopoverArrowDirection.Down
popController.barButtonItem = sender
popController.delegate = self
}
Whenever I click on the UIBarButtonItem, it presents the view in full screen, but shouldn't it be the size I specify in line 5?
Popovers are quite finicky now. First, you are going to want to configure the popoverPresentationController before you present it.
Secondly, make sure your arrow direction is pointing the way the arrow points and not where the content is respective to the UIBarButtonItem. So, if its inside UIToolbar (and is near the bottom of the screen) you'll want .Down otherwise if its a navigation bar (near the top) you'll want to use .Up.
#IBAction func distancePopOver( sender : UIBarButtonItem){
//Configure the Popover presentation controller
let popController = (controller.popoverPresentationController)!
popController.permittedArrowDirections = .Down // .Up
popController.barButtonItem = sender
popController.delegate = self
//a UIViewController that I created in the storyboard
let controller = storyboard!.instantiateViewControllerWithIdentifier("distancePopOver")
controller.modalPresentationStyle = .Popover
controller.preferredContentSize = CGSizeMake(200,30)
presentViewController(controller, animated: true, completion: nil)
}
Now if you got this far and its still not working, its because the popover's default behavior in a compact size class is to fill the screen. Since you are already setting your view controller to be the popover's delegate you'll just need to implement this delegate function: adaptivePresentationStyleForPresentationController(_:traitCollection:) and return .None for the presentation style. This will allow you to even show a real looking popover on the iPhone. See my blog post: iPhone Popover for a full example of doing this.
I'm using Swift 2 and xcode 7.1.1.
My app is a tabbar + navigationbar based application.
What I'd like to do:
From my first viewcontroller (CollectionVC) I have a collectionview of images(tabbar at bottom and navbar at top). When you select an image, I transition programmatically to a modalviewcontroller (ImageZoomVC) that allows them to zoom on the image (no tabbar or navbar). From the ImageZoomVC I want to transition programmatically to the UserProfileVC. The UserProfileVC should have the tabbar and navbar like the first view. The navbars back button should also take us back to the ImageZoomVC.
This workflow is similar to facebook. When you select an image, you go to a black screen with just that image and some more info. You can click on anyone tagged in the image and it will push their profile onscreen with the tabbar and navbar back in place.
The Problem:
Once in the ImageZoomVC, I can't transition to the UserProfileVC without losing the tabbar and navbar. I've been able to add a navbar programmatically but there is no back button, and setting a back button hasn't worked. Also, there is no tabbar.
Code:
From my CollectionVC, I transition to the ImageZoomVC from my collectioncell like this:
#IBAction func PhotoButtonPressed(sender: UIButton) {
let imageZoom = ImageZoomVC()
imageZoom.showFrom(self.parentView!)
}
Here is the showFrom function that presents the ImageZoomVC modally. This code is inside the ImageZoomVC:
public func showFrom(viewController: UIViewController) {
//Some stuff here, edited for length
viewController.presentViewController(self, animated: false) {
UIView.animateWithDuration(ImageZoomVC.TransitionAnimationDuration,
delay: 0,
options: [.BeginFromCurrentState, .CurveEaseInOut],
animations: {
[weak self] in
self?.collectionView.alpha = 1
self?.collectionView.transform = CGAffineTransformIdentity
},
completion: {
[weak self] finished in
self?.view.userInteractionEnabled = finished
}
)
}
}
This is the code I'm attempting to use to transition to the UserProfileVC with navbar and tabbar. This doesn't work. It will present the VC, but there is no tabbar or back button.
func userSelected (sender: UIButton) {
let vc = self.presentingViewController?.storyboard?.instantiateViewControllerWithIdentifier("User Profile") as! UserProfileVC
let newNav = UINavigationController(rootViewController: vc)
newNav.navigationBar.barTintColor = UIColor().specialPurple()
newNav.navigationBar.translucent = false
self.presentViewController(newNav, animated: true, completion: nil)
}
A couple notes: The ImageZoomVC doesn't exist in storyboard. It is called and instantiated programmatically.
The ImageZoomVC is based off Agrume from Github found here:
https://github.com/JanGorman/Agrume
I'd like to push the UserProfileVC like facebook does. This current code presents it from the bottom. The code pushViewController is not recognized here in xCode.
Let me know what you think. All thoughts are welcome. Thanks.
I'm trying to use MMDrawerController in my application, but I can't get the side drawer to close with gestures on the center view. I've used MMDrawerController somewhere else in my app with great success, but can't figure out why its not working in this case.
The top-level View Controller is a UINavigationController, whose default view controller is the MasterViewController (source below). This class extends MMDrawerController and configures the view for what I want (center and right, close gestures, max width). The center view has a button that opens the drawer. Once the drawer is open I can't close it with gestures on the center view. I added a button to the drawer and it can close the drawer programmatically, but I need to be able to tab/pan on the center view.
class MasterViewController: MMDrawerController {
override func viewDidLoad() {
let centerView = storyboard!.instantiateViewControllerWithIdentifier("CenterControllerName") as? CenterControllerType
super.setCenterViewController(centerView, withCloseAnimation: false, completion: nil)
let drawer = storyboard!.instantiateViewControllerWithIdentifier("Drawer") as? DrawerType
super.rightDrawerViewController = drawer
super.setMaximumRightDrawerWidth(200, animated: true, completion: nil)
super.closeDrawerGestureModeMask = MMCloseDrawerGestureMode.PanningCenterView | MMCloseDrawerGestureMode.TapCenterView
}
}
The function to open the drawer:
#IBAction func drawerButtonPressed(sender: AnyObject) {
drawer?.openDrawerSide(MMDrawerSide.Right, animated: true, completion: nil)
}
I was able to work around this by placing a ContainerView as the only object in my view and then configuring the MMDrawerContainer from my ViewController. It doesn't seem like the right answer but everything looks and functions right from the user's perspective.
Ok so I run into the same issue, and I am almost sure that it comes from this:
Ok, the VC1 (with the star) is our application Home, the VC2 is the left drawer, and the VC3 is the DrawerController.
During a long time I tried to put gesture functions in the VC1 and VC2, but only opening in the VC1, and closing in the VC2 would work.
The functions I used in VC1:
let rightSwipe = UISwipeGestureRecognizer(target: self, action: Selector("showDrawer:"))
rightSwipe.direction = .Right
view.addGestureRecognizer(rightSwipe)
...
func showDrawer(sender: UISwipeGestureRecognizer) {
if let m = mmdc {
if !m.isLeftDrawerOpen() {
m.toggleDrawerSide(MMDrawerSide.Left, animated: true, completion: nil)
}
}
}
And the same one in VC2 but with the LeftSwipe and closeDrawer.
The solution is tu put both of these functions and gestures recognizer in the VC3 (DrawerController).
The problem is coming from the fact that your gestures are defined for a given VC, but when you open the drawer, it changes the current VC by a new one, and the previous VC is just displayed but can't be interactif with. By putting things in the parentVC of VC1/VC2 it solves the problem.