I have an app that has a begin journey activity and a choose category activity. I want to make it that after the user presses the start journey button he won't be able to return there or be able with a certain button.
Set the next viewController as the root viewController as described here: How to set the rootViewController with Swift, iOS 7
It seems like you’re looking for the root view of the app to be changed to the beginning of the journey, rather than the initial home screen. This can be done by setting the rootViewController property of the app’s main window, UIApplication.shared.keyWindow.
This can be done using the following code block:
let viewController = JourneyViewController()
guard
let window = UIApplication.shared.keyWindow
else {
return
}
window.rootViewController = viewController
Please note, I work in Xcode 11 beta with iOS 13. My apologies if this doesn’t work with older versions of iOS/OS X.
Related
I'm migrating my macOS app built with SwiftUI 1 to SwiftUI 2. There is a feature that allows user to save the main view as pdf using NSPrinterOperation, which takes an NSView instance.
Currently, the app is on SwiftUI 1 with AppDelegate, and I can get the main view through this code
Button("Print") {
let appDelegate = NSApp.delegate as! AppDelegate
let view = appDelegate.window.contentView! // returns the NSHostingView set up in AppDelegate.swift
...
NSPrintOperation(view: view, printInfo: newInfo).run()
}
Since upgrading to SwiftUI2, the AppDelegate is no longer there, and how can I get the view now?
See my comment for reference how to set app delegate (which you will be able then access), however also you can content view directly from window via NSApp, like
NSApp.mainWindow?.contentView
or
NSApp.keyWindow?.contentView
depending on your windows configuration.
I'm designing a MacOS app, for which I'd like to have a second window appear on the first time the app is launched (similar to what Apple does on the first time you open iMovie or Pages). I've tried a couple things to no avail. So far, I've created a second group as a target of the original app. The new group contains the tutorial storyboard I designed and a custom class called OnboardingWindowController (a subclass of NSWindowController). I gave the window controller the Storyboard ID of OnboardingWindowController, and added the following method:
class func loadFromNib() -> OnboardingWindowController {
let vc = NSStoryboard(name: "Onboarding", bundle: nil).instantiateController(withIdentifier: "OnboardingWindowController") as! OnboardingWindowController
return vc
}
I'm not sure, however, how to get this to launch without prompting the first time the app is launched and then never again. Thanks in advance!
Add a key to userdefaults check it's value, if it's false then show the tutorial else don't.
if UserDefaults.standard.bool(forKey: "didShowTutorial") {
// Code to proceed without showing tutorial
} else {
UserDefaults.standard.set(true, forKey: "didShowTutorial")
// Code to show the tutorial
}
My application works as many, typically banking, apps do: when the user moves the app into background (e.g. by tapping on the Home button), the current visible ViewController is replaced by a launch screen. When the app is brought back to foreground, it displays the previous ViewController or some other ViewController (which depends on a number of conditions, such as, for example, the duration the app was in the background, etc. - but these are not important here).
On iOS 12 and earlier, I use a very simple mechanism - on applicationDidEnterBackground, I set the current ViewController to a local variable on AppDelegate and display the launch screen.
savedViewController = window?.rootViewController
On applicationWillEnterForeground, I check whether all required conditions are met and set the Window's ViewController to the stored ViewController.
window?.rootViewController = savedViewController
This no longer works on iOS 13. When the app enters foreground, the initial story boars is displayed. Setting the rootViewController on the current Window has no affect at all.
I tried to solve this issue by enabling scenes in my application, but that didn't work either.
In SceneDelegate, I'm able to set a default ViewControllerin the scene:willConnecTo method like this:
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
let launchStoryboard = UIStoryboard(name: "LaunchScreenVersion", bundle: Bundle.main)
let launchViewController = launchStoryboard.instantiateInitialViewController()
window?.rootViewController = launchViewController
window?.becomeKey()
The above code works, but the method is only called when the scene first loads. I then tried to move my code from from applicationWillEnterForeground to sceneWillEnterForeground, but this didn't work either. When I set the Window's ViewController in this method, that doesn't have any effect and only the ViewController set initially loads.
I also tried moving the code to sceneDidBecomeActive, but it had exactly the same effect.
I know that iOS has built-in state restoration, but, due to security policies, we can't use them in the app as no user state can be saved if the app is no longer running.
Any ideas how I can swap the ViewController with a splash screen when the app goes into background and set it back when the app goes into foreground?
Currently on my viewController : Upload, my button send the data to my database only if all the information are filled out, and I come back to the preview view (table View) with :
self.navigationController?.popViewControllerAnimated(true)
I would like, if it is possible, to come back to my main view on the tabBarController. I tried many things, like directly on the storyboard with Present modally segue to "TabBar controller", but I come back to the TabBar without sending my data to the database and without checking in the information are filled out..
How can I do it?
Thanks!
UITabBarController has a property selectedIndex with which you can switch the selected tab. So on completion after dismissing the UploadViewController you can run:
self.tabBarController?.selectedIndex = 0 // Index to select
It would probably be best to create a delegate for your UploadViewController to fire a function to do all the work in your previewVC on API call completion.
(Super late response...in case someone has similar questions, presumably in later version of Swift, such as mine which is Swift 5, iOS 13.2). Steps:
Be sure to set an id for your UITabBarController storyboard, e.g. "TabBarViewController"
Next, add the following to an action that has already been connected to a button:
let ID_TABBAR = "TabBarViewCOntroller"
#IBAction func returnToTabbar(_ sender: Any) {
let tabBarController = self.storyboard?.instantiateViewController(identifier:ID_TABBAR) as! UITabBarController
self.navigationController?.pushViewController(tabBarController, animated:true)
}
Referenced from one of the responses from this post.
Update: In case your Tab Bar View Controller also happens to be the root view controller, the two lines of the code in the returnToTabbar method above can be:
self.dismiss(animated:true, completion:nil);
self.navigationController?.popViewController(animated:true);
(ref.: See answer here, for Swift4 but works just fine in Swift5)
The unwind segue to the menu view is no longer working on XCode 7 with iOS 9.
The only way I got it to "work" is by changing the type of segue in the storyboard to an ECSlidingSegue from the default UIStoryboardSegue. the ability to change this in the storyboard for unwind segues seems to be new to XCode 7. When changed to the ECSlidingSegue it only shows the menu view itself and the view it was supposed to shift to the right (but still keep on the screen) disappears. All other segues seem to be working and I can confirm that all was working correctly in iOS 8 and XCode 6.
Any ideas why this would not be working?
It looks like ECSlidingViewController hasn't been updated for a year now.
In some of my apps I am using MMDrawerController which seems to do exactly the same and I can confirm that it works with iOS 9. And it is updated on a more regular basis. If you are interested in trying it you can check it here
No, but until it's fixed, you can show the menu from code:
- (IBAction)menuButtonTap
{
ECSlidingViewController *slidingViewController = (ECSlidingViewController *)self.view.window.rootViewController;
[slidingViewController anchorTopViewToRightAnimated:YES];
}
#IBAction func menuButtonTapped(sender: AnyObject) {
let slidingViewController = self.view.window!.rootViewController as? ECSlidingViewController
slidingViewController?.anchorTopViewToRightAnimated(true)
}
I managed to get it working correctly using swift by attaching each of the menu buttons in each of the view controllers to an IBAction function. I then put the code as it is above into each of these IBAction functions. The code uses the current instance of ECSlidingViewController (the current view) and then calls anchorTopViewToRightAnimated in order to correctly assign the current view that is being pulled to the right.