How can I add cover vertical animation while changing rootViewController - swift

I can add animation from options. But none of them are cover vertical. How can add cover vertical animation ?
guard let window = UIApplication.shared.windows.filter({$0.isKeyWindow}).first else {
return
}
guard let rootViewController = window.rootViewController else {
return
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "x") as! xTabBarController
vc.view.frame = rootViewController.view.frame
vc.view.layoutIfNeeded()
UIView.transition(with: window, duration: 0.2, options: .transitionCrossDissolve, animations: {
window.rootViewController = vc
}, completion: { completed in
})

Related

How to change rootViewController in swift?

I am working on an application in which there is no login logout feature. When user opens the application he sees main screen. Now there is an option in setting page named as Pin Lock application. When user select this option a PinScreen comes(like OTP Screen) then user sets the Pin. After that When user closes the application the Pin lock screen comes first asking user to enter pin.
So how can i do that?
if UserDefaults.standard.bool(forKey: "LoggedIn") == false {
let story = UIStoryboard(name: "Main", bundle:nil)
let vc = story.instantiateViewController(withIdentifier: "EnterPin") as! UINavigationController
UIApplication.shared.windows.first?.rootViewController = vc
UIApplication.shared.windows.first?.makeKeyAndVisible()
let enterPinViewController = self.storyboard.instantiateViewController(identifier: "EnterPinViewController") as! EnterPinViewController
self.navigationController.present(enterPinViewController, animated: true, completion: nil)
} else if UserDefaults.standard.bool(forKey: "LoggedIn") == true {
let story = UIStoryboard(name: "Main", bundle:nil)
let vc = story.instantiateViewController(withIdentifier: "MainController") as! UINavigationController
UIApplication.shared.windows.first?.rootViewController = vc
UIApplication.shared.windows.first?.makeKeyAndVisible()
let mainViewController = self.storyboard.instantiateViewController(identifier: "ViewController") as! ViewController
self.navigationController.present(mainViewController, animated: true, completion: nil)
}
Currently i am setting UserDefaults value as true and false and saving Pin in UserDefaults itself. I have tried changing rootViewController but nothing happening means every time main screen is coming instead of Pin Screen.
First you need to get the Window from SceneDelegate and use that window for rootViewController.
Suggestion: Whenever we are using rootViewController then no need to do present and push thing it will automatically set as a main home viewcontroller(Intial viewController)
let window = (UIApplication.shared.connectedScenes.first!.delegate as! SceneDelegate).window
let storyboard = UIStoryboard(name: "Main", bundle:nil)
if UserDefaults.standard.bool(forKey: "LoggedIn") == false {
let vc =storyboard.instantiateViewController(withIdentifier: "EnterPin") as! UINavigationController
window?.rootViewController = vc
window?.makeKeyAndVisible()
} else if UserDefaults.standard.bool(forKey: "LoggedIn") == true {
let vc =storyboard.instantiateViewController(withIdentifier: "MainController") as! UINavigationController
window?.rootViewController = vc
window?.makeKeyAndVisible()
}
I suggest you do all this things in SceneDelegate file
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: scene)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if UserDefaults.standard.bool(forKey: "LoggedIn") == false {
let vc = storyboard.instantiateViewController(withIdentifier: "EnterPin") as! UINavigationController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
} else if UserDefaults.standard.bool(forKey: "LoggedIn") == true {
let vc = storyboard.instantiateViewController(withIdentifier: "MainController") as! UINavigationController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
}
}
I Hope it is helpful for you!
let viewController = MainViewController()
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
guard let window = appDelegate.window else {
return
}
window.rootViewController = viewController

The Push notification not redirecting while tapping

I have implemented the redirection code in appdelegate while we tap on the push notification. The app is opening to its home page and not redirecting to the particular page.
The issue I found during debugging
When the application is in foreground or background the notification is redirected to the particular page but when the application is terminated from the background the notification is not redirecting to the particular page only the home page is displaying.
is anyone can suggest a good solution for this? The following code is used for redirection.
func directions(activity: String,info:[String:Any], currentView:UIViewController){
if let _ = UserDefaults.standard.value(forKey: "user_id"){
let storyboard = UIStoryboard.init(name: "Home", bundle: nil)
let homeView = storyboard.instantiateViewController(withIdentifier: "HOMEViewController") as! HOMEViewController
if #available(iOS 13.0, *) {
UIApplication.shared.statusBarStyle = .lightContent
self.navigatinController = UINavigationController(rootViewController: homeView)
self.navigatinController.isNavigationBarHidden = true
self.window!.rootViewController = self.navigatinController
self.window!.makeKeyAndVisible()
}else{
self.window?.rootViewController = homeView
}
switch activity {
case "CHAT_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Chat", bundle: nil)
let chat = storyboard.instantiateViewController(withIdentifier: "ChatHomeViewController_new") as! ChatHomeViewController_new
chat.segmentTag = 0
chat.isFromPush = true
chat.pushId = info["user_id"] as! String
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(chat, animated: false)
}else{
self.window?.rootViewController?.present(chat, animated: false, completion: nil)
}
case "GROUP_CHAT_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Chat", bundle: nil)
let chat = storyboard.instantiateViewController(withIdentifier: "ChatHomeViewController_new") as! ChatHomeViewController_new
chat.segmentTag = 1
chat.isFromPush = true
chat.pushId = info["group_id"] as! String
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(chat, animated: false)
}else{
self.window?.rootViewController?.present(chat, animated: false, completion: nil)
}
case "JOURNAL_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let journalView = storyboard.instantiateViewController(withIdentifier: "JournalViewController") as! JournalViewController
journalView.url = info["id"] as! String
journalView.isFromPush = true
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(journalView, animated: false)
}else{
self.window?.rootViewController?.present(journalView, animated: false, completion: nil)
}
case "NEWS_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let newsPage = storyboard.instantiateViewController(withIdentifier: "NewPageViewController") as! NewPageViewController
newsPage.isFromPush = true
newsPage.pushDate = info["id"] as! String
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(newsPage, animated: false)
}else{
self.window?.rootViewController?.present(newsPage, animated: false, completion: nil)
}
case "FORUM_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let forum = storyboard.instantiateViewController(withIdentifier: "ForumViewController") as! ForumViewController
forum.isFromPush = true
forum.isFromPushId = info["id"] as! String
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(forum, animated: false)
}else{
self.window?.rootViewController?.present(forum, animated: false, completion: nil)
}
case "EVENT_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let eventsView = storyboard.instantiateViewController(withIdentifier: "EventViewController") as! EventViewController
eventsView.isFromPush = true
eventsView.pusteventId = info["id"] as! String
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(eventsView, animated: false)
}else{
self.window?.rootViewController?.present(eventsView, animated: false, completion: nil)
}
case "KNOWLEDGE_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let knowledge = storyboard.instantiateViewController(withIdentifier: "KnowledgeCenterViewController") as! KnowledgeCenterViewController
knowledge.titleValue = "Knowledge Center"
knowledge.id = info["id"] as! String
knowledge.isFromPush = true
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(knowledge, animated: false)
}else{
self.window?.rootViewController?.present(knowledge, animated: false, completion: nil)
}
case "LEGAL_ACTIVITY":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let knowledge = storyboard.instantiateViewController(withIdentifier: "KnowledgeCenterViewController") as! KnowledgeCenterViewController
knowledge.titleValue = "Legal Updates"
knowledge.id = info["id"] as! String
knowledge.isFromPush = true
if #available(iOS 13.0, *){
(self.window?.rootViewController as! UINavigationController).pushViewController(knowledge, animated: false)
}else{
self.window?.rootViewController?.present(knowledge, animated: false, completion: nil)
}
default:
showHomeView()
}
}else{
showLoginScreen()
}
}

Black screen flashes between Launch and first ViewController in SceneDelegate

I am using SceneDelegate.swift to decide which ViewController is shown with this code:
guard let windowScene = (scene as? UIWindowScene) else { return }
if Auth.auth().currentUser != nil {
AuthenticationService.automaticSignIn(onSuccess: {
let window = UIWindow(windowScene: windowScene)
self.window = window
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Login", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "TabBarControllerID") as! TabBarController
window.rootViewController = newViewcontroller
window.makeKeyAndVisible()
}, onError: {
let window = UIWindow(windowScene: windowScene)
self.window = window
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Login", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "LoginViewControllerID") as! LoginViewController
window.rootViewController = newViewcontroller
window.makeKeyAndVisible()
})
} else {
let window = UIWindow(windowScene: windowScene)
self.window = window
let mainstoryboard:UIStoryboard = UIStoryboard(name: "Login", bundle: nil)
let newViewcontroller:UIViewController = mainstoryboard.instantiateViewController(withIdentifier: "LoginViewControllerID") as! LoginViewController
window.rootViewController = newViewcontroller
window.makeKeyAndVisible()
}
}
Between the transition, a black screen appears (in my .gif for about 0.2 seconds), depending on the loading time. Sorry for the bad quality and the short duration, but you will see it:
Where does this black screen come from?
try to change this line:-
self.window!.rootViewController = UINavigationController(rootViewController: DashboardVC)
self.window!.makeKeyAndVisible()
The issue seems to be caused by a 'gap' in the presentation between the launch-storyboard and the window that is made visible. The appleIDProvider is async.
A workaround, rather than a fix, is to present a temporary View (with the same color or content as your launch-storyboard) and replace it once authorization is done;
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: TempView())
self.window = window
window.makeKeyAndVisible()
let user = User.shared
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: user.id) { (credentialState, error) in
switch credentialState {
case .authorized:
DispatchQueue.main.async {
user.authenticated = true
window.rootViewController = UIHostingController(rootView: HomeView(showAlert: false, showSendview: false, showAccountview: false))
}
default:
DispatchQueue.main.async {
user.authenticated = false
window.rootViewController = UIHostingController(rootView: SignInView().environment(\.window, window))
}
}
}
}

Perform segue in AppDelegate

When a Firebase token is invalid, I want that the user is redirect to my app loginVC. This is my code:
func userErrorLogout() {
print("user error logout")
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: ViewController = storyboard.instantiateViewController(withIdentifier: "loginVC") as! ViewController;
let rootViewController = self.window!.rootViewController as! UINavigationController;
rootViewController.pushViewController(viewController, animated: true);
}
I get an error on "let rootViewController:.... = 2019-11-27 13:03:49.364864+0100 Geo[25133:2193886] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file
Since SWIFT is new to me, I am not able to debug this message. How do I perform the redirection?
you need to use the below code :
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: ViewController = storyboard.instantiateViewController(withIdentifier: "loginVC") as! ViewController;
let window = (UIApplication.shared.delegate as! AppDelegate).window!
DispatchQueue.main.async {
window.rootViewController = viewController
}
You need to assign the value for your rootViewController. Try this:
func userErrorLogout() {
print("user error logout")
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: ViewController = storyboard.instantiateViewController(withIdentifier: "loginVC") as! ViewController;
let nav = UINavigationController(rootViewController: viewController)
self.window?.rootViewController = nav
}
You need to set the viewcontroller to window. You can do like below. This code also has transition animation it gives fade to transition.
// MARK: WINDOW SET
func gotoIntro() {
UIView.transition(with: window!, duration: 0.5, options: .transitionCrossDissolve, animations: {
UIView.performWithoutAnimation({
let introStoryboard = UIStoryboard(name: "Intro", bundle: nil)
let navigationController = introStoryboard.instantiateInitialViewController() as! UINavigationController
self.window?.rootViewController = navigationController
})
}, completion: nil)
}
As of iOS 13, pushing a VC at the start of a launch is not possible from AppDelegate anymore (Not 100% sure).
You must use SceneDelegate if you wish to present the view from your root.
To do so, simply do this inside your SceneDelegate file. I have tested this approach on my own app and is working 100%
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
// check if the token is valid
if valid {
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "yourVC")
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
}
else {
// token is invalid
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewController(identifier: "invalidVC")
let rootNC = UINavigationController(rootViewController: rootVC)
self.window?.rootViewController = rootNC
self.window?.makeKeyAndVisible()
}
}

Check if user already exists Firebase swift 3.0

let database = FIRDatabase.database().reference()
database.child("Users").queryOrderedByKey().observe(.childAdded, with: { (snapshot) in
print(snapshot)
if let value = snapshot.value as? [String: AnyObject] {
let ui = value["id"] as! String
if ui != FIRAuth.auth()!.currentUser!.uid
{
var storyboard = UIStoryboard(name: "Main", bundle: nil)
if s == true
{
storyboard = UIStoryboard(name: "Main", bundle: nil)
}
else if p == true
{
storyboard = UIStoryboard(name: "big", bundle: nil)
}
else if se == true
{
storyboard = UIStoryboard(name: "se", bundle: nil)
}
else if os == true
{
storyboard = UIStoryboard(name: "4s", bundle: nil)
}
else if ip1 == true
{
storyboard = UIStoryboard(name: "ipad1", bundle: nil)
}
else if ipb == true
{
storyboard = UIStoryboard(name: "ipadbig", bundle: nil)
}
let naviVC = storyboard.instantiateViewController(withIdentifier: "eula")as! UIViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = naviVC
}
else
{
var storyboard = UIStoryboard(name: "Main", bundle: nil)
if s == true
{
storyboard = UIStoryboard(name: "Main", bundle: nil)
}
else if p == true{
storyboard = UIStoryboard(name: "big", bundle: nil)
}
else if se == true
{
storyboard = UIStoryboard(name: "se", bundle: nil)
}
else if os == true{
storyboard = UIStoryboard(name: "4s", bundle: nil)
}
else if ip1 == true
{
storyboard = UIStoryboard(name: "ipad1", bundle: nil)
}
else if ipb == true
{
storyboard = UIStoryboard(name: "ipadbig", bundle: nil)
}
let naviVC = storyboard.instantiateViewController(withIdentifier: "yo")as! UIViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = naviVC
}
}
})
I have a firebase app, and I want to check if a user exists in my databse, If the don't i want to display a licenses agreement, but if they do i don't have too. My current method only works if there are two users. Thank you for your help in advance.
I figured it out
let database = FIRDatabase.database().reference()
database.child("Users").observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
print(snapshot)
if snapshot.hasChild( FIRAuth.auth()!.currentUser!.uid)
{
All you need to do is change .ChildAdded to .value. This will make sure its reading the data when you start.
With that code I think it will only execute when a child is added. I can't check it out right now but try with
database.child("Users").queryOrderedByKey().observe(.Value, with:{ (snapshot) in
...
})
As I said I can't check it so answer me if you have any problem. Good luck!