How to add animation delay in Modal View presentation swift iOS - ios

#objc func popCartView(tapGestureRecognizer: UITapGestureRecognizer)
{
let modalViewController = CartViewController()
modalViewController.modalPresentationStyle = .overCurrentContext
self.present(modalViewController, animated: true, completion: nil)
}
How to animate this view with more time like 2 seconds to complete animation

#objc func popCartView(tapGestureRecognizer: UITapGestureRecognizer)
{
let modalViewController = CartViewController()
modalViewController.modalPresentationStyle = .overCurrentContext
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
// Your code with delay
self.present(modalViewController, animated: true, completion: nil)
}
}

Related

Pause animation when modal view controller is presented

I have two animation which play on my home screen view controller. They are both animations from LottieFiles. One is an alpha colored changing background and the other is an infinite loop with different colors. When a new modal view over current context is selected I want to pause both animations and start them up again once the modal view is dismissed.
I have tried calling the animationView.pause method however they still continue to play in the background. I would like to pause them for better energy efficiency.
class HomeScreen: UIViewController{
let animationView = AnimationView()
let animationTwo = AnimationView()
func showSupport() {
let modalViewController = SupportViewController()
modalViewController.modalPresentationStyle = .overCurrentContext
present(modalViewController, animated: true, completion: nil)
}
func showSInfo() {
let modalViewController = InfoViewController()
modalViewController.modalPresentationStyle = .overCurrentContext
present(modalViewController, animated: true, completion: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
animationView.play(fromProgress: 0,
toProgress: 1,
loopMode: LottieLoopMode.loop,
completion: { (finished) in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
})
animationTwo.play(fromProgress: 0,
toProgress: 1,
loopMode: LottieLoopMode.loop,
completion: { (finished) in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
})
}
override func viewDidLoad() {
let animation = Animation.named("bg12")
animationView.animation = animation
animationView.contentMode = .scaleAspectFill
view.addSubview(animationView)
let animationViewTwo = Animation.named("infi2")
animationTwo.animation = animationViewTwo
animationTwo.contentMode = .scaleAspectFit
animationTwo.alpha = 0.7
view.addSubview(animationTwo)
}
}
class SupportViewController: UIViewController {
let homeVC = HomeScreen()
override func viewDidLoad() {
homeVC.animationView.pause()
homeVC.animationTwo.pause()
super.viewDidload()
}
}
Can't you put the pausing to the completion handler of the present, like:
present(modalViewController, animated: true) {
self.animationView.pause()
}

Custom popup over UITableViewController is swipe-able - how to prevent - Swift

I am trying to make a custom pop up over a UITableViewController that is embedded in a UINavigationController but I am experiencing two problems:
The opacity that i determined by designating an alpha value to the background colour of the UIViewcontroller for the pop up appears not to function.
The UIViewcontroller for the popup is swipe-able. If I make a left to right gesture on the screen I am able to push off the pop up. How do I prevent it from behaving like this? I am trying to show a file upload progress so it is important that the pop up is not able to be swiped away.
Please see screen shot below.
func showProgrssBarPopUp(){
let popUp = self.storyboard?.instantiateViewController(withIdentifier: "uploadPopUp") as! ProgressBarPopUpViewController
self.navigationController?.pushViewController(popUp, animated: true)
}
The lower viewcontroller content is not viewable, even though alpha value of overlaying popup viewcontroller is set to 0.5:
The entire viewcontroller for popup is swipe-able:
You can set alpha of background
self.view.backgroundColor = UIColor.white.withAlphaComponent(0.2)
You can Present ProgressBar View with modalPresentationStyle as overCurrentContext
let popUp = self.storyboard?.instantiateViewController(withIdentifier: "uploadPopUp") as! ProgressBarPopUpViewController
popUp.modalPresentationStyle = .overCurrentContext
self.present(popUp, animated: true, completion: nil)
Just override view controller's appear/dismiss method
class PopUpController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if animated {
view.backgroundColor = .clear
UIView.animate(withDuration: animationTime) {
self.view.layer.backgroundColor = UIColor.black.withAlphaComponent(0.75).cgColor
}
}
}
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
if flag {
UIView.animate(withDuration: animationTime, animations: {
self.view.layer.backgroundColor = UIColor.clear.cgColor
}, completion: { (bool) in
super.dismiss(animated: false, completion: completion)
})
} else {
super.dismiss(animated: flag, completion: completion)
}
}
}
Use
let popUp = PopUpController()
popUp.modalPresentationStyle = .overCurrentContext
self.present(popUp, animated: true, completion: nil)

Working with DispatchQueue in swift

I am using dispatcQueue to automatically dismiss my controller but I have an issue is that it dismiss my view controller automatically but also dismiss other view controllers that are presented modally and I want to dismiss only a single view controller
func dismissViewController() {
let pickVc = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "request-VC") as! RequestViewController
pickVc.modalPresentationStyle = .custom
pickVc.requestDelegate = self
present(pickVc, animated: true, completion: nil)
}
func openRequestAlertViewController() {
let pickVc = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "requestAlertVC") as! RequestAlertViewController
pickVc.modalPresentationStyle = .custom
pickVc.searchDelegate = self
present(pickVc, animated: true, completion: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
self.dismiss(animated: true, completion: nil)
}
}
func dismissRequestVC() {
let searchVc = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "searching-VC") as! SearchingViewController
searchVc.modalPresentationStyle = .custom
present(searchVc, animated: true, completion: nil)
}
but it also dismiss after 20 seconds and I don't want to dismiss this. any help? This is my whole code
Create an instance for a particular viewcontroller which you want to dismiss like the following
var lvc: LoadingViewController?
func showLoadingIn(viewController: UIViewController) {
lvc = LoadingViewController() // create new instance before presentation
viewController.presentViewController(lvc!, animated: false, completion: nil)
}
func dismissLoader() {
lvc?.dismissViewControllerAnimated(true) {
print("Dismissing Loader view Controller")
}
}
You are presenting all viewControllers with the current viewController and while dismissing you are are not dismissing the currently presented viewController. Instead you are dismissing the presenter viewController so all the presented ViewControllers are also getting dismissed.
If you want to dismiss a particular viewController you can do it like this,
yourViewController.dismiss(animated: true, completion: nil)
For example in your case you can do this to dismiss the pickVc after 20 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
pickVc.dismiss(animated: true, completion: nil)
}

How to show image in overCurrentContext view in the ViewController2.swift class?

How to show image in overCurrentContext view in the ViewController2.swift class ? I am doing this correctly when i worked manually but not doing when i using this programmatically in swift.
ViewController1.swift code -
#IBAction func btnImage(_ sender: Any)
{
let imageVC = self.storyboard?.instantiateViewController(withIdentifier: "ImageVC") as! ImageVC
self.navigationController?.pushViewController(imageVC, animated: true)
}
ViewController2.swift code -
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: true)
self.navigationController?.modalPresentationStyle = .overCurrentContext
}
I want this background alpha 0.7 and using .overCurrentContext
Output -
You are pushing your viewController, Instead you should present it with modalPresentationStyle .overCurrentContext. Do something like this:
#IBAction func btnImage(_ sender: Any)
{
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ImageVC") as! ImageVC
vc?.view.backgroundColor = UIColor.black.withAlphaComponent(0.7)
vc?.modalPresentationStyle = .overCurrentContext
vc?.navigationController?.isNavigationBarHidden = true
self.navigationController?.present(vc, animated: true, completion: nil)
}
For more information you can read more about modalPresentationStyle in Apple Docs.
Hope it helps!!

How to dismiss the current ViewController and change to the new ViewController in Swift?

I am new to iOS swift. I have three ViewController.
The page-A is root controller and it will present to the page-B. It has a timer in page-B. After 5 sec, it will change View from page-B to page-C , and close the page-B at the same time.
In the ViewControll-B
class AViewController: UIViewController {
var timer: Timer?
override func viewDidLoad() {
super.viewDidLoad()
//set the timer , and chagne view to C ViewController
Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(self.changeToAnswerView),
userInfo: nil,
repeats: false)
}
#objc func changeToAnswerView() {
dismissLoader()
}
func dismissLoader() {
dismiss(animated: true) {
print("Dismissing Loader view Controller")
}
}
override func viewWillDisappear(_ animated: Bool) {
//change view to Answer ViewController
let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "CViewControllerID")
filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
self.present(filterVC, animated: true, completion: nil)
}
}
After timer execute for 5 sec , the BViewController will dismiss itself and present to the BViewController.
But the following error will happened:
whose view is not in the window hierarchy
Did I missing something?
Question:
How to dismiss the current ViewController and change to the new ViewController in Swift?
Thanks in advance.
Here is the Working code that you can Try
Your Controller which is Dismissed and Tend to make a new controller being presented
import UIKit
class pdfVC: UIViewController
{
var timer : Timer?
override func viewDidLoad()
{
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(pdfVC.timerAction), userInfo: nil, repeats: false)
}
#objc func timerAction()
{
if timer != nil {
timer?.invalidate()
dismiss(animated: true, completion: {
print("Dismissed")
})
}
}
override func viewWillDisappear(_ animated: Bool) {
if self.isBeingDismissed {
let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "demoViewController")
filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
print("called")
self.presentingViewController?.present(filterVC, animated: true, completion: nil)
}
}
}
Output
Try changing dismissLoader function to something like:
func dismissLoader() {
dismiss(animated: true) {
print("Dismissing Loader view Controller")
if let presentingController = self.presentingViewController {
let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BViewControllerID")
filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
presentingController.present(filterVC, animated: true, completion: nil)
}
}
}
and remove the viewWillDisappear function.
The problem is that you are trying to present the BViewController from the loader after being dismissed (i.e removed from window hierarchy) which at that point doesn't exist.
So, the solution is that you could get a reference to the presenting view controller which is presenting the loader and which will appear after dismissing the loader and present the new view controller from there.
in your B view controller after its dismissed,
in its completion handler
self.dismiss(animated: true) {
if let presentingVC = self.presentingViewController {
present c view controller here
}
}
this above is one way to do so, another way is, through delegate
in A view controller:
if let bVC = self.storyboard.instantiateViewController(withIdentifier: B.controllerIdentifier) as? B {
bVC.delegate = self
self.present(bVC, animated: true, completion: nil)
}
inside B View Controller
add delegate method for Protocol
protocol BProtocol: class {
func didClose()
}
and in B dismiss
var delegate: BProtocol?
self.dismiss(animated: true) {
self.delegate?.didClose()
}
this delegate will be implemented by A ViewController as
extension AViewController: BProtocol {
func didClose() {
//present C
}
}
You are trying use a reference (instance) of view controller, that would no longer exist in memory.
Try this
if let presentingVC = self.presentingViewController {
let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "CViewControllerID")
filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
presentingVC.present(filterVC, animated: true, completion: nil)
}
Note: Present a new view controller (filterVC) once your current view controller is dismissed. A view controller can present only a one view controller at time (if you choose present modally). Perform this operation after a delay of 1 second..
Edit
Try with this edited code.
Class AViewController: UIViewController {
var timer: Timer?
var presentingVC: UIViewController?
override func viewDidLoad() {
super.viewDidLoad()
//set the timer , and chagne view to C ViewController
Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(self.changeToAnswerView),
userInfo: nil,
repeats: false)
}
#objc func changeToAnswerView() {
dismissLoader()
}
func dismissLoader() {
dismiss(animated: true) {
print("Dismissing Loader view Controller")
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//change view to Answer ViewController
if let presentingVC = self.presentingViewController {
self.presentingVC = presentingVC
}
}
override func viewWillDisappear(_ animated: Bool) {
//change view to Answer ViewController
super.viewWillDisappear(animated)
if let presentingVC = self.presentingVC {
let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "CViewControllerID")
filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
presentingVC?.present(filterVC, animated: true, completion: nil)
} else {
print("Presenting View controller is nil")
}
}
}

Resources