SwiftUI SceneDelegate Issue - ios

Within SceneDelegate.swift the following code is returning the error message "Use of unresolved identifier 'ContentView'; did you mean 'ContentMode'?".
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options
connectionOptions: UIScene.ConnectionOptions) {
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()
}
This error creates a failure in the program build. It's surprising since when I create a new project with the exact same SceneDelegate.swift, there is no issue with ContentView.
If I change ContentView to ContentMode it returns the error 'ContentMode' cannot be constructed because it has no accessible initializers".
Has anyone else had this issue? Just curious where I should start looking or what I have done wrong.

Figured this one out. If anyone else is curious I changed the ContentView.swift file name but didn't update it in SceneDelegate.swift.
So if you change the ContentView.swift file to BetterNameView.swift you need to update the above code in SceneDelegate.swift from ContentView() to BetterNameView()

Related

Correct way to get the screen size on iOS, after UIScreen.main deprecation

I always used UIScreen.main.bounds.size to get the screen size on iOS and worked fine.
Now (in iOS 16, I believe) when I try to access the screen size with the "main" instance of UIScreen a warning is displayed:
"main' will be deprecated in a future version of iOS: Use a UIScreen instance
found through context instead: i.e, view.window.windowScene.screen
So my question is:
What is the correct way to get the screen size? for simplicity let's imagine we are on the iPhone with, consequently, only one screen available. Thank you
From a ViewController:
let screenSize = self.view.window?.windowScene?.screen.bounds.size
Per Apple discussion on UIScreen.main deprecation:
Apple discourages the use of this symbol. Use a UIScreen instance
found through context instead. For example, reference the screen that
displays a view through the screen property on the window scene
managing the window containing the view.
Here is an extension to find the UIScreen instance through context:
extension UIViewController {
func screen() -> UIScreen? {
var parent = self.parent
var lastParent = parent
while parent != nil {
lastParent = parent
parent = parent!.parent
}
return lastParent?.view.window?.windowScene?.screen
}
}
For reference, this is the same UIScreen instance associated with the windowScene in the SceneDelegate:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
let screen = windowScene.screen
configureNavigationBar()
}

RootViewController's constraints get removed after calling VNDocumentCameraViewController

After presenting and dismissing the VNDocumentCameraViewController, I get a black screen. After some research, I found that a few constraints disappear after dismissing the camera view controller.
Here is a comparison of the view hierarchy before and after the VNDocumentCameraViewController.
Changes I noticed:
UILayoutContainerView's constraints are completely gone
RootTabBarContoller's constraints are halved.
"Position and size are ambiguous" sign
And here is the view hierarchy when the VNDocumentCameraViewController is present.
The root view controller is initialized in a scene delegate like this:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else {
return
}
window = UIWindow(windowScene: windowScene)
window?.rootViewController = RootTabBarController()
window?.makeKeyAndVisible()
}
I was thinking to try a storyboard as the initial scene but all my views use XIBs and I could not find how to import them into a storyboard.
Does the root view controller (RootTabBarController in my case) need extra constraints or some other configuration in order to sustain such transitions?
So, the solution was rather trivial. For some reason, the RootTabBarController had view.translatesAutoresizingMaskIntoConstraints = false line that caused the issue with the constraints.
Removing this line solved the issue.

Failed to instantiate the default view controller after switching from .xcodeproj to .xcworkspace

When I create a brand new project in Xcode and choose Storyboard for the interface, I can run the app on my phone just fine.
However, when I do pod install (the only deps I added are pod 'Plaid') and then switch over to the .xcworkspace file, I get this error:
[WindowScene] Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set?
I have tried the usual fixes (check Is Initial View Controller etc.)
Appreciate any help, thanks.
You must assign entry point to your project, go to your sceneDelegate file and set it like this:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
window?.backgroundColor = .white // or the color that you prefer
window?.makeKeyAndVisible()
let controller = ViewController() // or the first controller presented in your app
window?.rootViewController = controller
}

How do I make onboarding scene disappear after first launching app Xcode 11 iOS 13

I'm very new to this and I've run into a problem. My goal is to make an onboarding screen welcoming you to the app. I want this to disappear after launching the app for the first time. I have followed this tutorial. Instead of putting the code in AppDelegate, I have put the code in SceneDelegate under:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
...
this is my code till now:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let launchedBefore = UserDefaults.standard.bool(forKey: "hasLaunched")
self.window? = UIWindow(frame: UIScreen.main.bounds)
let launchStoryboard = UIStoryboard(name: "Main", bundle: nil)
let mainStoryboard = UIStoryboard(name: "actual", bundle: nil)
var vc: UIViewController
if launchedBefore
{
vc = mainStoryboard.instantiateInitialViewController()!
}
else
{
vc = launchStoryboard.instantiateViewController(identifier: "firststoryboard")
}
UserDefaults.standard.set(true, forKey: "hasLaunched")
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
Now I don't get any errors, but when I launch the app the screen is black. Does anyone know what I'm doing wrong?
I don't know if you found the answer, but I just asked a essentially the same question and had it answered: How to make Onboarding work with Scene Delegate in iOS13?

Xcode 11, Main Interface fixed with Main.storyboard [duplicate]

This question already has answers here:
Cannot change Main.storyboard's name on iOS 13 [Xcode 11 GM seed 2]
(2 answers)
Closed 3 years ago.
Main Interface is not changing with another storyboard in Xcode 11, it always run with Main.storyboard after changing with another storyboard, I have checked "is initial View Controller" after using a View Controller in new Storyboard.
I have tested in Xcode 10, it was working fine.
Did I miss something in Xcode 11?
In plist.
Swift 5 with iOS 13
One more changes require in info.plist file under Application
Scene Manifest group.
Change name in Application Scene Manifest also.
Additional:
If you want to create the root window without a storyboard, you need removing the Main storyboard file base name and Storyboard Name item from Info.plist, and create the window programmatically in SceneDelegate:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
#available(iOS 13.0, *)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
// continue to create view controllers for window
}
//......
}
Can you please change "Main storyboard file base name" to your storyboard file name.

Resources