DismissViewController Swift - ios

My app has the following flow if the user is logged in
Loading Screen -----> Main Screen -----> Rest of App
and the following flow if he's not :
Loading Screen -----> Login Screen -----> Main Screen -----> Rest of App
Now I am implementing the Logout feature. I have added the following code into main Screen :
func handleLogout() {
if self.presentingViewController != nil {
var vc = self.presentingViewController
while ((vc!.presentingViewController) != nil) {
vc = vc!.presentingViewController
}
vc?.dismissViewControllerAnimated(true, completion: {
})
}
}
This works fine if the 1st path is followed (the user was logged in when the app was launched) as the app returns to the Loading Screen and then loads up the Login Screen as expected. However, if the 2nd path was followed (the user was not logged in when the app was launched, and Login Screen has been used) this code leads to the Login Screen being opened directly and the whole logout process failing. Is there a way I can ensure that the Loading Screen is the one which is always loaded by this code regardless of which of the two paths have been followed.

Use unwind segues!
You basically add an unwind segue connecting your "main screen" and "login screen". Give it an identifier and you can initiate the segue whenever you want. In handleLogout:
func handleLogout() {
self.performSegueWithIdentifier("your identifier", sender: self)
}
For details of how to create an unwind segue: https://www.andrewcbancroft.com/2015/12/18/working-with-unwind-segues-programmatically-in-swift/

This is just a suggestion here goes:
In AppDelegate file you can do something similar to this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//Implement this method
let userLoggedIn = isUserLoggedIn();
if !userLoggedIn {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
//Instantiate the login view controller
window?.rootViewController = storyboard.instantiateViewControllerWithIdentifier("login")
window?.makeKeyAndVisible()
}
return true
}
Now when the app starts it'll first check the user's login state and display the appropriate view.
Note: this is assuming you use storyboards and the root view controller is set to the Main Screen

If you are using Storyboards, I would suggest creating storyboard that is used purely for your login view/s. Then in the AppDelegate DidFinishLoading method, you can show the login storyboard if they need to login or show the main storyboard if they are already logged in. You can swap out storyboards at anytime and its easy to do. That will help simplify the flow a bit. This is what I usually do in my apps. If you need sample code just let me know.

Related

How to check in AppDelegate, on start of the application, if the firebase user already exists and is logged in?

I'm developing an iOS App with swift4 and Firebase, I'm searching how to check in AppDelegate, on start of the application, if the firebase user already exists and is logged in?
The situation is:
user open the app and logged in with username and password and firebase.
user close the app.
user reopen the app and if the user was cancelled from firebase, I would to redirect him to login/registration page.
If I use var user = firebase.auth().currentUser the user result always logged in, but I have cancelled him from firebase.
Ho can I do that?
Create a function to return boolean if the user is logged in or not.
func isUserLoggedIn() -> Bool{
return Auth.auth().currentUser != nil
}
then create another function to redirect him wherever you want
func routeInitialVC(with identifier:String ){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: identifier)
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
}
Finally, just use the Boolean function in your AppDelegate with the ternary operator to make it shorter and apply the routing function
authHelper.isUserLoggedIn() ? routeInitialVC(with: "HomeVC") : routeInitialVC(with: "AuthVC")

How to add a view controller to window programmatically and bring it to front

I want to do a screen saver for the whole app, but i only can do for 1 screen...now i am changing to appdelegate to start the timer and show the screen saver as a whole...However, i not sure how to add the video screen saver(video player view) as a whole at app delegate window... Timer i did edi, it really print out "Play Video" after 5 second, but the video view didn't show out.
library used:
1. https://github.com/piemonte/Player
2. timer
Please use this if it works for you.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginSignupVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}
If Not works, then I suggest using one initial UIViewController for this video screen and change to next screen when a video is completed.
UIApplication.shared.keyWindow?.rootViewController?.addChildViewController(self.player)
UIApplication.shared.keyWindow?.addSubview(self.player.view)
this is the best solution.
Credit to : senior Desmond
Not sure but you can try adding video on launcher screen, or if you want the video should run, in that case you need to follow these simple steps
Add a Movie player on applicationDidLaunch
when video finishes on it return back method you need to load you app controller.
I hope this helps do let me know in case you need anything more to help.
[Edit as per the requirement]
I think you need to create a controller in the app delegate
you need to create a class function in your app delegate where you can add a movie player to the screen with auto play on.
also you need to maintain a timer, but be careful while using timer and read well about it, as it needs to be manage very carefully else results in various crashes.
You can manage the timer by getting touch events on the screen by the following logic like
if movieplayer is on screen then, remove movie player else,
invalidate timer and restart the timer
The function with timer will does the following things
invalidate timer
add movie player on the window and bring it to the main screen.

How to redirect a hybrid application to home page instead of tutorial page in Ionic ios application?

Currently i am developing an Hybrid application using ionic. So my application normally contains an intro view and after the intro view it goes straight to the home page. When i kill the application i need to show the home page instead of tutorial view while launching again. Since i am a native iOS developer i am pretty clear about managing it in the native ios code like this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if (NSUserDefaults.standardUserDefaults().objectForKey("login") == nil)
{
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "login")
}
if (NSUserDefaults.standardUserDefaults().boolForKey("login") == true)
{
do {
let arr1 = try UserProfileDataHelper.find("1")
if arr1?.Type == "Customer" {
currentUser = "Customer"
screenlaunch("MENU")
}else{
currentUser = "Store"
screenlaunch("HOME")
}
} catch _{}
}
return true
}
func screenlaunch(str : String )
{
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController = mainStoryboard.instantiateViewControllerWithIdentifier(str)
let navigationController :UINavigationController = UINavigationController(rootViewController: homeViewController)
navigationController.navigationBarHidden = true
window!.rootViewController = nil
window!.rootViewController = navigationController
window?.makeKeyWindow()
}
How to achieve the same in the ionic application . Please have an idea on this. After my research i found that my fellow old colleague had made use of:
console.log("didTutorial: "+$localStorageProvider.get('didTutorial'));
if( $localStorageProvider.get('didTutorial') ){
$urlRouterProvider.otherwise('/app/hero');
}
else{
$urlRouterProvider.otherwise('/');
}
Is it something related to state change?
You can use below concept of loading Root page based on condition.
As per your requirement first time you need to load Tutorial Page Navigation flow and on 2nd load you don't need Tutorial page as first page.
So for that do as mention below.
Step1: Add one variable rootPage: any; in your app.component.ts page.
Step2: Bind that rootPage in your app.html file where it deside which root page will be load at startup of your app.
<ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>
Step3: Now in your app.component.ts page check condition that Tutorial page seen by user or not and based on that assign rootPage like below.
initializeApp() {
this.platform.ready().then(() => {
//retrieve isAppRunFirstTime from DB storage
if (!isAppRunFirstTime) {
this.rootPage = TutorialPage;
} else {
this.rootPage = HomePage;
}
}
}
Note : isAppRunFirstTime is flag which decide your app is loading at
first time.
above flag you can store in Storage DB and at first time app load make it True in your DB.
Hope this will help you to load conditional root page in your app.

iOS: how to delay the launch screen?

When launch an app, the LaunchScreen.xib is removed as soon as all the assets are initialized.
I want to make the launch screen stay for at least 1 sec.
Is there a way to achieve this?
Thank you!
You can create a view controller that uses the LaunchScreen storyboard, present it (not animated) on applicationDidFinishLaunching or applicationWillFinishLaunching, and dismiss it whenever you want.
Keep in mind this is discouraged by Apple because it gives the impression that your app takes a lot longer to launch, which is bad user experience and might cause some of your users to delete your app.
Swift 4 Update
Just write one line of code
Thread.sleep(forTimeInterval: 3.0)
in the method of didfinishLauching.... in appdelegate class.
Example
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Thread.sleep(forTimeInterval: 3.0)
// Override point for customization after application launch.
return true
}
Never sleep on the main thread. Doing this could actually cause iOS to kill your app for taking too long to start up
Thought I chip in my thoughts on this, I wanted to write in comments but it won't allow many lines. I believe many apps developer want to do this (delay the launch screen) is because they want to build a brand presence of the apps/games for their company.
Having said that, launch screen is NOT designed for that, as Rick Maddy explained in the comment section in one of the other answers. Launch screen's purpose is to make users feel the app is instantly running by showing the empty UI while the actual data is loading at the back (willAppear and so on).
So to achieve what many developers want, while being in-line with Apple's HIG, what you can do is:
Display UI template in the launchscreen as intended by Apple HIG.
Upon main screen load, load up another VC that shows "intro" of your brand. Make sure this runs only ONCE (a simple flag in
NSUserDefaults should do the trick).
Users should be allowed to skip this if it is a long "intro".
The same "intro" VC should be available to user by tapping on a "View Intro" button somewhere (maybe in about page).
If you want to go with simple, you can use NSThread:
[NSThread sleepForTimeInterval:(NSTimeInterval)];
You can put this code into the first line of applicationDidFinishLaunching method.
For example, display default.png for 1.0 seconds.
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
[NSThread sleepForTimeInterval:1.0];
}
It will stop splash screen for 1.0 seconds.
Alhamdulellah Solution is find
Only copy and paste this code in AppDelegate Class
Call this SplashScreenTiming() in didFinishLaunchingWithOptions()
private func SplashScreenTiming(){
let LunchScreenVC = UIStoryboard.init(name: "LaunchScreen", bundle: nil)
let rootVc = LunchScreenVC.instantiateViewController(withIdentifier: "splashController")
self.window?.rootViewController = rootVc
self.window?.makeKeyAndVisible()
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(DismissSpalshController), userInfo: nil, repeats: false)
}
#objc func DismissSpalshController(){
let mainVC = UIStoryboard.init(name: "Main", bundle: nil)
let rootvc = mainVC.instantiateViewController(withIdentifier: "SignInVC")
self.window?.rootViewController = rootvc
self.window?.makeKeyAndVisible()
}

Parse Seamless Login

I have created an app using parse with Swift , when a user opens the app (not from the background) the login screen shows for a split second before moving to the main view. I wan't it to go straight to the main screen if the user is logged in.
I have tried putting the following code nearly everywhere.
if PFUser.currentUser() != nil {
}
I tried NSUserDefaults to check if the user is logged in, in the app delegate didFinishLaunching, couldn't get it to work.
Any help would be greatly appreciated , thanks.
You need to put the check into your "AppDelegate.swift" file.
Then depending on if the user is logged in or not load the MAIN viewcontroller or the LOGIN viewcontroller.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Other stuff you need to setup the app...
if PFUser.currentUser() == nil
{
//Load the Login ViewController
}
else
{
//Load the Main ViewController
}
return true
}

Resources