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()
}
}
Related
I want to pass viewController type as a function just like the code below
extension UIViewController {
func switchScreen(storyboardName:String,viewControllerName:String,vcc:UIViewController) {
let mainStoryboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: viewControllerName) as? vcc {
self.present(viewController, animated: true, completion: nil)
}
}
}
but xcode returns an error that says Cannot find type 'vcc' in scope
I tried adding .Type in the parameter after UIViewController but the error is the same.
any solutions?
The third parameter must be a type, not an instance
extension UIViewController {
func switchScreen<T : UIViewController>(storyboardName: String, viewControllerName: String, type: T.Type) {
let mainStoryboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: viewControllerName) as? T {
self.present(viewController, animated: true, completion: nil)
}
}
}
and call it
switchScreen(storyboardName: "Main",
viewControllerName: "Foo",
type: LoginViewController.self)
But as instantiateViewController and also present don't care about the static type you don't need it, this is sufficient
extension UIViewController {
func switchScreen(storyboardName: String, viewControllerName: String) {
let mainStoryboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: viewControllerName)
self.present(viewController, animated: true, completion: nil)
}
}
To avoid a crash you could add an enum with the available view controller identifiers and pass this type in the second parameter for example
enum ControllerIdentifier : String, RawRepresentable {
case foo, bar
}
extension UIViewController {
func switchScreen(storyboardName: String, viewControllerName: ControllerIdentifier) {
let mainStoryboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: viewControllerName.rawValue)
self.present(viewController, animated: true, completion: nil)
}
}
Use generic param
extension UIViewController {
func switchScreen<T: UIViewController>(storyboardName:String,viewControllerName:String,vcc:T) {
let mainStoryboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: viewControllerName) as? T {
self.present(viewController, animated: true, completion: nil)
}
}
}
I am programming on swift language and I want to reuse this code passing the identifier as String and the page as the view controller name, but I am getting the error Use of undeclared type 'page', how can I achieve this? thanks
func toReuseSession(identifier: String, **page**: UIViewController){
let mainStoryBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let mainVC = mainStoryBoard.instantiateViewController(withIdentifier: identifier) as? **page** else {
return
}
mainVC.modalPresentationStyle = .fullScreen
present(mainVC, animated: true, completion: nil)
}
According to your function, You should be declared a generic type of UIViewController in such a way you can achieve your output. I have modified your function in a correct syntax, You can use that:-
func toReuseSession<T:UIViewController>(identifier: String, page: T){
let mainStoryBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let mainVC = mainStoryBoard.instantiateViewController(withIdentifier: identifier) as? T else {
return
}
mainVC.modalPresentationStyle = .fullScreen
present(mainVC, animated: true, completion: nil)
}
Now you can call your function like that:-
self.toReuseSession(identifier: "NewPasswordViewController", page: NewPasswordViewController())
// "NewPasswordViewController" is in my case when I was checking it's working. You can change whatever ViewController wants to present.
This is a possible solution with generics but you have to pass the static type in the second parameter
extension UIViewController {
func toReuseSession<T>(identifier: String, page: T.Type) where T : UIViewController {
let mainStoryBoard = UIStoryboard(name: "Main", bundle: .main)
guard let mainVC = mainStoryBoard.instantiateViewController(withIdentifier: identifier) as? T else {
return
}
mainVC.modalPresentationStyle = .fullScreen
present(mainVC, animated: true, completion: nil)
}
}
I have a keyboard extension and want the user to be able to tap on "settings", and be taken to the settings page inside the actual app. I was pretty excited when I got that working, but I realized that the page wasn't inside the navigation controller anymore!
Here is my code. How can I augment it to present a specific sub-screen inside my 'TransparentNavigationController'?
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let urlPath : String = url.path as String!
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if(urlPath == "/inner"){
let innerPage: myStampsVC = mainStoryboard.instantiateViewController(withIdentifier: "myStampsVC") as! myStampsVC
self.window?.rootViewController = innerPage
}
self.window?.makeKeyAndVisible()
return true
}
I've tried different mixes of
let navigationController = window?.rootViewController as! UINavigationController
let innerPage = navigationController.viewControllers[4] as! myStampsVC
but I'm missing something. Thanks for any nudges in the right direction.
Here's the answer:
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let urlPath = url.path
if(urlPath == "/inner"){
func showMyStamps(in navigationController: UINavigationController) {
navigationController.popToRootViewController(animated: false)
_ = navigationController.topViewController?.view
let innerViewController = myStampsVC() as UIViewController
navigationController.pushViewController(innerViewController, animated: false)
}
switch window!.rootViewController {
case let demo as DemoScreen:
if let navC = demo.presentedViewController as? UINavigationController {
showMyStamps(in: navC)
} else {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let navC = storyBoard.instantiateViewController(withIdentifier: "TransparentNavController") as! UINavigationController
demo.present(navC, animated: false)
showMyStamps(in: navC)
}
case let navC as UINavigationController:
showMyStamps(in: navC)
default: assertionFailure()
}
}
return true
}
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!
I am developing a walkthrough screen which should appear only the first time when the user opens the app. So far I created the walkthrough page and PageViewController.
See the picture:
I read lots of similar questions here and I understood that I have to use
UserDefaults()
inside the AppDelegate, but I didn't understand how to use the class and storyboard names inside the code.
Basically, when the app is opened for the first time, the PageViewController should appear on the screen and when the user clicks on the start button, which is on the WalkThroughScreen it will dismiss the tutorial page and the app will start.
I have tried this code:
if let isFirstStart = UserDefaults.standard.value(forKey: "isFirstLaunch") as? Bool {
if defaults.bool(forKey: "isFirstLaunch") {
defaults.set(false, forKey: "isFirstLaunch")
let mainStoryboard = UIStoryboard(name: "WalkThroughScreen", bundle: Bundle.main)
let vc : WalkThroughScreen = mainStoryboard.instantiateViewController(withIdentifier: "PageViewController") as! WalkThroughScreen
self.present(vc, animated: true, completion: nil)
}
I am pretty sure that it is a complete mess, because I didn't understand it very good and I haven't used the TutorialPage, so I will be very thankful if someone leave me hints or example how to do it correctly
Yes you are right, you have to use userDefaults to achieve this. And you have to do it inside appDelegate()
Roel Koops answer should do it but you can try it like this also:
let launchedBefore = UserDefaults.standard.bool(forKey: "launchedBefore")
if launchedBefore {
print("This is not first launch.")
} else {
print("This is first launch.")
UserDefaults.standard.set(true, forKey: "launchedBefore")
UserDefaults.standard.synchronize()
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc : WalkThroughScreen = mainStoryboard.instantiateViewController(withIdentifier: "WalkThroughScreen") as! WalkThroughScreen
self.present(vc, animated: true, completion: nil)
}
And make sure to declare: let userDefaults = UserDefaults.standard and use it inside didFinishLaunchingWithOptions.
There are even more solutions so I give you one more:
let userDefaults = UserDefaults.standard
if !userDefaults.bool(forKey: "launchedBefore") {
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc : WelcomeViewController = mainStoryboard.instantiateViewController(withIdentifier: "WalkThroughScreen") as! WelcomeViewController
self.window?.makeKeyAndVisible()
self.window?.rootViewController?.present(vc, animated: false, completion: nil)
userDefaults.set(true, forKey: "launchedBefore")
userDefaults.synchronize()
}
You can even declare all the storyboard thing in one line:
self.window?.rootViewController = self.storyboard?.instantiateViewController(withIdentifier: "WalkThroughScreen")
But this assumes that you declare 2 variables:
var window: UIWindow?
var storyboard: UIStoryboard?
If it didn't work just tell me, I am gonna try to help.
The code in your if-block is never executed if the key "isFirstLaunch" doesn't exist.
Try this:
if let isFirstStart = UserDefaults.standard.value(forKey: "isFirstLaunch") as? Bool {
print("this is not the first launch")
} else {
print("this is the first launch")
UserDefaults.standard.set(false, forKey: "isFirstLaunch")
UserDefaults.standard.synchronize()
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc : WalkThroughScreen = mainStoryboard.instantiateViewController(withIdentifier: "WalkThroughScreen") as! WalkThroughScreen
self.present(vc, animated: true, completion: nil)
}