I am trying to show a custom view on a dismiss of a controller. It's working fine if I am sowing it on popViewController but not working when I am using dismiss method. If anybody knows the solution please help me out.
// presenting screen from HomeController
guard let controller = UIStoryboard(name: "EmptyWorkout", bundle: nil).instantiateViewController(withIdentifier: "LogWoroutVC") as? LogWorkoutViewController else { return }
controller.modalPresentationStyle = .overFullScreen
self.present(controller, animated: true, completion: nil)
// dimissing screen from LogWorkoutViewController
#IBAction func backButtonAction(_ sender: UIButton) {
let window = UIApplication.shared.windows.last
let timerView = UINib(nibName: "WorkoutTimer", bundle: nil).instantiate(withOwner: nil, options: nil).first as? WorkoutTimer
if let timerView = timerView {
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
if let tabBarYPosition = self.tabBarController?.tabBar.frame.origin.y {
let yPosition = tabBarYPosition - 60
timerView.frame = CGRect(x: 0, y: yPosition, width: screenWidth, height: 60)
window?.addSubview(timerView)
}
}
self.dismiss(animated: true, completion: nil)
}
According to the docs, the presenting controller is responsible for the actual dismiss. When the presented controller dismisses itself, it will ask the presenter to do it for it. In here you need to use the closure or protocol. for e.g use like
on your LogWorkoutViewController VC / presented VC declare the variable as like
var dismissedVC : ((Bool) -> Void)?
There is a Boolean property inside UIViewController called isBeingDismissed that you can use for this purpose:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isBeingDismissed {
// TODO: called the closures
dismissedVC!(true)
}
}
on your button action call only dismiss VC
#IBAction func backButtonAction(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
on your HomeController when you present call the closure also.
guard let controller = UIStoryboard(name: "EmptyWorkout", bundle: nil).instantiateViewController(withIdentifier: "LogWoroutVC") as? LogWorkoutViewController else { return }
controller.modalPresentationStyle = .overFullScreen
controller.dismissedVC = { result in
// call your WorkoutTimer view
self.workoutTimer()
}
self.present(controller, animated: true, completion: nil)
func workoutTimer() {
let window = UIApplication.shared.windows.last
let timerView = UINib(nibName: "WorkoutTimer", bundle: nil).instantiate(withOwner: nil, options: nil).first as? WorkoutTimer
if let timerView = timerView {
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
if let tabBarYPosition = self.tabBarController?.tabBar.frame.origin.y {
let yPosition = tabBarYPosition - 60
timerView.frame = CGRect(x: 0, y: yPosition, width: screenWidth, height: 60)
window?.addSubview(timerView)
}
}
}
Created a SingleViewApplication in that I have placed a button.
Now clicking on button I need to display a tableView as popover.
The TableViewController is created in xib.
The issue is tableViewController.popoverPresentationController always comes as nil see below code
let filterVC = TableViewController(nibName: "TableViewController", bundle: nil)
var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
filterDistanceViewController.preferredContentSize = CGSize(width: 300, height: 200)
let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .any
if let pop = filterDistanceViewController.popoverPresentationController {
pop.delegate = self
}
in above code
filterDistanceViewController.popoverPresentationController is always coming as nil
Any hint in right direction will be highly appreciated.
Until you've set a modalPresentationStyle on your VC, the popoverPresentationController property will be nil. Ensure that you set the modalPresentationStyle before accessing.
You are not presenting anything, so you need to present the popoverPresentationViewController on the current viewcontroller, for example:
#IBAction func importantButtonPressed(_ sender: UIButton) {
let tableViewController = UITableViewController()
tableViewController.modalPresentationStyle = .popover
present(tableViewController, animated: true, completion: nil)
if let pop = tableViewController.popoverPresentationController {
pop.delegate = self
}
}
You may do like below.
#IBAction func popoverBtnPressed(_ sender: Any) {
let vc2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController2")
vc2.modalPresentationStyle = .popover
vc2.popoverPresentationController?.delegate = self
vc2.popoverPresentationController?.barButtonItem = popoverBtn
vc2.popoverPresentationController?.sourceRect = .zero
present(vc2, animated: true, completion: nil)
}
I'm trying to add my view controller as pop up controller. But everyt ime i use the code the view comes sliding from bottom and not as i wish. Below is the code i'm using
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let popupVC = storyboard.instantiateViewController(withIdentifier: "WSFilterViewController") as! WSFilterViewController
popupVC.modalPresentationStyle = UIModalPresentationStyle .popover
popupVC.preferredContentSize = CGSize (width: 300, height:300)
let pVC = popupVC.popoverPresentationController
pVC?.permittedArrowDirections = UIPopoverArrowDirection.any
pVC?.delegate = self as? UIPopoverPresentationControllerDelegate
self.present(popupVC, animated: true, completion: nil)
I want it as in the image shown
Any help will be appreciated.
Thanks in advance
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let popupVC = storyboard.instantiateViewController(withIdentifier: "WSFilterViewController")
popupVC.modalPresentationStyle = UIModalPresentationStyle .popover
popupVC.preferredContentSize = CGSize(width: 170, height: 130)
popupVC.popoverPresentationController?.delegate = self
popupVC.popoverPresentationController?.sourceView = sender as? UIView // button
popupVC.popoverPresentationController?.sourceRect = (sender as AnyObject).bounds
self.present(popupVC, animated: true, completion: nil)
The issue was something different and figured it out now.
Thanks everyone
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle
{
return .none
}
you must add the code above on iPhone devices, otherwise it will keep showing full screen.
I am presenting my viewController like so using accessoryButtonTappedForRowWith:
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let popoverContent = storyboard.instantiateViewController(withIdentifier: "Test")
popoverContent.modalPresentationStyle = .popover
if let popover = popoverContent.popoverPresentationController {
let viewForSource = self.createCharacterView as UIView
popover.sourceView = viewForSource
// the position of the popover where it's showed
popover.sourceRect = viewForSource.bounds
// the size you want to display
popoverContent.preferredContentSize = CGSize(width: 200,height: 200)
popover.delegate = self
}
self.present(popoverContent, animated: true, completion: nil)
The pop up works and looks fine it's just that the viewController that I am presenting needs to the label of the tableViewCell. I am able to get the variable, but I'm unsure how to pass the variable to the popover since a segue isn't called I don't think I am able to use prepare(for segue: UIStoryboardSegue, sender: Any?).
It was too simple:
popoverContent.variableName = passingVariable
You might need to cast you popOvercontent to you specific viewController
(popoverContent as? MyViewController).myVar = value
I got an error message during navigating from first view controller to second view controller. My coding is like this one
let vc = LoginViewController(nibName: "LoginViewController", bundle: nil)
self.navigationController?.pushViewController(vc, animated: true)
The problem is I always got this kind of error message
2014-12-09 16:51:08.219 XXXXX[1351:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </var/mobile/Applications/FDC7AA0A-4F61-47E7-955B-EE559ECC06A2/XXXXX.app> (loaded)' with name 'LoginViewController''
*** First throw call stack:
(0x2efcaf0b 0x39761ce7 0x2efcae4d 0x31b693f9 0x31ac1eaf 0x3191e365 0x317fe895 0x318a930d 0x318a9223 0x318a8801 0x318a8529 0x318a8299 0x318a8231 0x317fa305 0x3147631b 0x31471b3f 0x314719d1 0x314713e5 0x314711f7 0x3146af1d 0x2ef96039 0x2ef939c7 0x2ef93d13 0x2eefe769 0x2eefe54b 0x33e6b6d3 0x3185d891 0x4ccc8 0x4cd04 0x39c5fab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I already found the answer
Swift 4
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "nextView") as! NextViewController
self.present(nextViewController, animated:true, completion:nil)
Swift 3
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("nextView") as NextViewController
self.presentViewController(nextViewController, animated:true, completion:nil)
Try this one. Here "LoginViewController" is the storyboardID specified in storyboard.
See below
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("LoginViewController") as LoginViewController
self.navigationController?.pushViewController(secondViewController, animated: true)
XCODE 8.2 AND SWIFT 3.0
Present an exist UIViewController
let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.present(loginVC, animated: true, completion: nil)
Push an exist UIViewController
let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.navigationController?.pushViewController(loginVC, animated: true)
Remember that you can put the UIViewController Identifier following the next steps:
Select Main.storyboard
Select your UIViewController
Search the Utilities in the right
Select the identity inspector
Search in section identity "Storyboard ID"
Put the Identifier for your UIViewController
If you want to navigate to Controller created Programmatically, then do this:
let newViewController = NewViewController()
self.navigationController?.pushViewController(newViewController, animated: true)
If you want to navigate to Controller on StoryBoard with Identifier "newViewController", then do this:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
self.present(newViewController, animated: true, completion: nil)
Swift3:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController("LoginViewController") as UIViewController
self.navigationController?.pushViewController(vc, animated: true)
Try this out. You just confused nib with storyboard representation.
You can move from one scene to another programmatically using below code :
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let objSomeViewController = storyBoard.instantiateViewControllerWithIdentifier(“storyboardID”) as! SomeViewController
// If you want to push to new ViewController then use this
self.navigationController?.pushViewController(objSomeViewController, animated: true)
// ---- OR ----
// If you want to present the new ViewController then use this
self.presentViewController(objSomeViewController, animated:true, completion:nil)
Here storyBoardID is value that you set to scene using Interface Builder.
This is shown below :
See mine.
func actioncall () {
let loginPageView = self.storyboard?.instantiateViewControllerWithIdentifier("LoginPageID") as! ViewController
self.navigationController?.pushViewController(loginPageView, animated: true)
}
If you use presenting style, you might lose the page's navigation bar with preset pushnavigation.
Programmatically there are different ways based on different situations
load storyenter code hereboard nib file
let yourVc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourViewController") as! YourViewController;
self.present(yourVc, animated: true, completion: nil)
Load from xib
let yourVc = YourViewController.init(nibName: "YourViewController", bundle: nil)
self.present(yourVc, animated: true, completion: nil)
Navigate through Segue
self.performSegue(withIdentifier: "your UIView", sender: self)
let VC1 = self.storyboard!.instantiateViewController(withIdentifier: "MyCustomViewController") as! ViewController
let navController = UINavigationController(rootViewController: VC1)
self.present(navController, animated:true, completion: nil)
XCODE 9.2 AND SWIFT 3.0
ViewController to NextViewcontroller without Segue Connection
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "NextViewController") as! NextViewController
self.navigationController?.pushViewController(nextViewController, animated:true)
or
let VC:NextViewController = storyboard?.instantiateViewController(withIdentifier: "NextViewController") as! NextViewController
self.navigationController?.pushViewController(VC, animated: true)
You can do navigation between view controllers using code with the help of storyboard and storyboardId of the view controller.
This code is for Swift 3:
let signUpVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
self.navigationController?.pushViewController(signUpVC, animated: true)
In addition to the good answers above to set the navigation view controller on top of your screen on your app, you can add it to your AppDelegate.swift file inside the block as follows
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
window?.makeKeyAndVisible()
window?.rootViewController = UINavigationController(rootViewController: LoginViewController())
return true
}
let vc = DetailUserViewController()
vc.userdetails = userViewModels[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
I'm not sure try below steps,i think may be error occurs below reasons.
you rename some files outside XCode. To solve it remove the files from your project and re-import the files in your project.
check and add missing Nib file in Build phases->Copy bundle resources.finally check the nib name spelling, it's correct, case sensitive.
check the properties of the .xib/storyboard files in the file inspector ,the property "Target Membership" pitch on the select box,then your xib/storyboard file was linked with your target.
such as incorrect type of NIB.Right click on the file and click "Get Info" to verify that the type is what you would expect.
I Give you my code to make a transition.
In this example the action is connecting to an UIButton. So don't forget to set it.
Don't forget to set the name of your ViewController in the transition method.
Don't forget to set your storyboard too. Your need to have one view per viewController. Connect each ViewController to each view in storyBoard. You can see on the screenshoot bellow
class PresentationViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var playButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
let image = UIImage(named: "YourPlayButton") as UIImage?
playButton.frame = CGRectMake(0, 0, 100, 100)
playButton.center = CGPointMake(self.view.frame.width/2, self.view.frame.height/2)
playButton.addTarget(self, action: "transition:", forControlEvents: UIControlEvents.TouchUpInside)
playButton.setBackgroundImage(image, forState: UIControlState.Normal)
self.view.addSubview(playButton)
}
func transition(sender:UIButton!)
{
println("transition")
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("YourSecondViewController") as UIViewController
let window = UIApplication.sharedApplication().windows[0] as UIWindow
UIView.transitionFromView(
window.rootViewController!.view,
toView: secondViewController.view,
duration: 0.65,
options: .TransitionCrossDissolve,
completion: {
finished in window.rootViewController = secondViewController
})
}
}
If you are building UI without drag and drop (without using storyboard)
and want to navigate default page or ViewController.swift to another page?
Follow these steps
1) add a class (.swift)
2) Import UIKit
3) Declare class name like
class DemoNavigationClass :UIViewController{
override func viewDidLoad(){
let lbl_Hello = UILabel(frame: CGRect(x:self.view.frame.width/3, y:self.view.frame.height/2, 200, 30));
lbl_Hello.text = "You are on Next Page"
lbl_Hello.textColor = UIColor.white
self.view.addSubview(lbl_Hello)
}
}
after creating second page come back to first page (ViewController.swift)
Here make a button in viewDidLoad method
let button = UIButton()
button.frame = (frame: CGRect(x: self.view.frame.width/3, y: self.view.frame.height/1.5, width: 200, height: 50))
button.backgroundColor = UIColor.red
button.setTitle("Go to Next ", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.addSubview(button)
now define buttonAction method outside of viewDidLoad() in same class
func buttonAction(sender: UIButton!)
{
let obj : DemoNavigationClass = DemoNavigationClass();
self.navigationController?.pushViewController(obj, animated: true)
}
Keep one thing that i forget
in main.storyboard there is a scene with a arrow,
select that arrow and press delete button
now drag and drop a navigationcontroller and delete tableview which comes with navaigation controller.
select navigationcontroller press control on keyboard and drag it in to another scene on storyboard that is ViewController.
This mean that your viewcontroller become root viewcontroller
hope this help you
Thanks
in main.storyboard , drag and drop navigationcontroller,
let signUpVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
// self.present(signUpVC, animated: false, completion: nil)
self.navigationController?.pushViewController(signUpVC, animated: true)
Swift 4.0.3
#IBAction func registerNewUserButtonTapped(_ sender: Any) {
print("---------------------------registerNewUserButtonTapped --------------------------- ");
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "RegisterNewUserViewController") as! RegisterNewUserViewController
self.present(nextViewController, animated:true, completion:nil)
}
Change our Controller Name RegisterNewUserViewController
I think you are looking for something like this:
let signUpViewController = SignUpViewController()
present(signUpViewController, animated: true, completion: nil)
If you want full screen of the new page:
present(signUpViewController, animated: true, completion: nil)
Hope this helps :)