I created a sample iOS app, where I removed the storyboard, the launch screen, the SceneDelegate and created a blank UIViewController
MainViewController:
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
}
AppDelegate:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = MainViewController()
window?.makeKeyAndVisible()
return true
}
}
Info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>
My problem is that my view is not taking the whole height of the screen, I thought that
UIWindow(frame: UIScreen.main.bounds) should suffice but I keep getting this screen
"where I removed ... the launch screen"
This is the issue. All iOS apps MUST have a launch screen storyboard, even if the rest of the app is done without storyboards. This is at least true for UIKit based apps, not sure about SwiftUI apps.
Without a launch screen storyboard the app falls back to only supporting old 3.5" (or maybe 4") iOS device sizes. This results in the black bars (known as letter boxing) on larger devices. The inclusion of the launch screen storyboard tells the app that it can handle all possible screen sizes.
Your launch screen storyboard should replicate a greatly simplified version of your app's initial screen. The whole idea is to give the user the illusion of your app launching faster than it really does. Though the utility of this has diminished on newer, faster hardware.
Related
This question already has answers here:
How to remove Scene Delegate from iOS Application?
(6 answers)
Closed last month.
Edit
I mistakenly selected "Multiplatform" instead of "iOS" when creating the project.
Simply select "iOS" to create the project and things will be done the traditional way.
I want to start a new project in Xcode 14.2 with just AppDelegate and UIKit, without SwiftUI or SceneDelegate.
The method up to Xcode 13 does not seem to work.
1. Create new project in Xcode 14.2
2. Add AppDelegate.swift
import UIKit
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = MyViewController()
window!.makeKeyAndVisible()
return true
}
}
3. Add MyViewController.swift
import UIKit
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemGreen
print("viewDidLoad() called.")
print("frame:", view!.frame)
}
}
When the application is launched, a green screen is expected to appear, but a black screen is displayed.
Print statements are output correctly.
At this time, the following warning appears.
Adding UIApplicationSceneManifest key to Info.plist will remove this warning, but the black screen will remain. (Previously, this key was not needed for apps that did not use multiple windows.)
[SceneConfiguration] Info.plist contained no UIScene configuration dictionary (looking for configuration named "(no name)")
What simple something am I missing?
I assume you want to invoke your app by initializing a UIViewController and don't care much about the underlying UIResponder objects.
Create a new project by selecting Storyboard as the desired Interface preference (You won't use a storyboard after all).
Then add your first View Controller to the window object. And if you'd like to access your AppDelegate you can do it from anywhere as below.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let window = window else { return }
let vc = UIViewController()
vc.view.backgroundColor = .systemGreen
window.rootViewController = vc
window.makeKeyAndVisible()
let appDelegate = UIApplication.shared.delegate as? AppDelegate
}
}
Correct me if your intention of omitting UIWindowSceneDelegate is of other nature, such as supporting iOS 12
I'll start with the main problem: My issue is not easily reproducible.
So... In my app, depending on whether it's the first time the user opens it, I am changing the rootViewController.
I do so like this:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if /* code to figure out if it's the first launch */ {
let storyboard = UIStoryboard(name: "Onboarding", bundle: nil)
let onboardingViewController = storyboard.instantiateInitialViewController()
window?.rootViewController = onboardingViewController
}
return true
}
}
And this basically works great! As I am currently building that Onboarding ViewController, I removed the if and therefore it always get's displayed. This also worked fine, but all of a sudden the app would not start any more. The screen stays black. I then run the exact same code on an other device and it's working there.
Btw. the code above is all there is in my AppDelegate and the issues persists if the OnboardingVC has everything commented out.
When looking at the UI-Debugger for my app it also looks strange:
Normally there would be an arrow next to the UIWindow showing that it's root is indeed my VC, but in my case that's not the case.
I wouldn't mind and just delete the app from my device and reinstall it afterwards, but I've had one user-complaint for an other app of mine which users the same logic, who told me about the exact problem. Now I basically reproduced the issue but have no idea on where the problem should be.
My app is using storyboards btw.
Maybe somebody had that problem before and has any idea on what might be the problem.
EDIT:
Just had the problem again today... Here are some more observations:
When I initiate my ViewController and output it's view, it's not correct. It's not the view that is really set in the storyboard. It's a random other view.
Is it possible, that the storyboard is corrupt? And if so... what can I do about it?
After I added a random subview to my Main-View-Controllers view and run again, it worked again... So obviously the storyboard somehow got corrupt?
Ok... while development... ok... but for an app that's out there and all of a sudden the storyboard get's corrupt... that is really bad!!!!
Did anybody have that problem before? And how to solve it?
try this
in your case window is nil so
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
if /* code to figure out if it's the first launch */ {
let storyboard = UIStoryboard(name: "Onboarding", bundle: nil)
let onboardingViewController = storyboard.instantiateInitialViewController()
window?.rootViewController = onboardingViewController
}
return true
}
}
I've finally figured out the problem. For whatever reason I obviously double-linked the view outlet of my Initial-View-Controller to a subview. So it had two outlets to the view property (how is that even possible?)
And it randomly picked on or the other on startup....
Took a very sharp eye of a friend to see the problem :)
So I've created a new iOS single view application with no core data, no test and then I deleted Main.storyboard and the launch screen storyboard.
I want to do as much in code as I can so I can understand what I'm doing (since I'm just learning iOS programming). The thing is, that I just cant fill the whole iPhone X screen with a background image. I've tried this first using storyboards and had no problem whatsoever. Am I missing something?
// AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let mainController = MainController()
window?.rootViewController = mainController
window?.makeKeyAndVisible()
return true
}
}
// MainController.swift
import UIKit
class MainController: UIViewController {
let background: UIImageView = {
let image = UIImageView(image: #imageLiteral(resourceName: "bg"))
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
}
extension MainController {
override func viewDidLoad() {
super.viewDidLoad()
setupBackground()
}
}
extension MainController {
func setupBackground() {
view.addSubview(background)
NSLayoutConstraint.activate([
background.leadingAnchor.constraint(equalTo: view.leadingAnchor),
background.trailingAnchor.constraint(equalTo: view.trailingAnchor),
background.topAnchor.constraint(equalTo: view.topAnchor),
background.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
To summarize the comments above, you need to use a launch storyboard in order for iOS to give you a UIScreen that covers the device's full bounds.
If you don't already have a launch storyboard, create one in Xcode 11 via File > New > File... > Launch Screen. Then make sure to select that launch storyboard under your app target > General > Launch Screen File.
Somehow XCode starts partially draw non-retina images on both retina iPhone and Simulator. You can see image with standard searchbar below, it is even not my graphics, but as you can see magnifier is pixelated, while text is retina. Some of both my and system graphics are still retina, some not. I'm trying to clean project and restart XCode.
Turns out it's because I initialized my ViewController before application: didFinishLaunchingWithOptions:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
let viewController = UITableViewController()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// add viewController to view hierarchy
}
}
I am new to Objective C and Swift. Here I am having an exception as 'NSInternalInconsistencyException' in my sample program. I do the following steps and this is my first program in Swift and I am not familiar in Objective C.
Create an empty application name as SampleTesting
Created a CheckingController.xib
Created a AppDelegate.swift
Created a CheckingController.swift
CheckingController.xib:
I have created a Sample Button.
AppDelegate.swift:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var navigationController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
// Override point for customization after application launch.
self.window!.backgroundColor = UIColor.whiteColor()
self.window!.makeKeyAndVisible()
var mainController: CheckingController? = CheckingController(nibName: "CheckingController", bundle: nil)
self.navigationController = UINavigationController(rootViewController: mainController)
self.window!.rootViewController = self.navigationController
return true
}
func applicationWillResignActive(application: UIApplication) {
}
CheckingController.swift:
import Foundation
import UIKit
class CheckingController: UIViewController{
init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Need some guidance on what could be going wrong here and how to resolve it.
Thanks.
I followed the below steps and i fixed the error:
Open the XIB file causing problems
Click on file’s owner icon on the left bar (top one, looks like a yellow outlined box)
If you don’t see the right-hand sidebar, click on the third icon above “view” in your toolbar. This will show the right-hand sidebar
In the right-hand sidebar, click on the third tab–the one that looks a bit like a newspaper
Under “Custom Class” at the top, make sure Class is the name of the ViewController that should correspond to this view. If not, enter it In the right-hand sidebar, click on the last tab–the one that looks like a circle with an arrow in it
You should see “outlets” with “view” under it. Drag the circle next to it over to the “view” icon on the left bar (bottom one, looks like a white square with a thick gray outline
Save the xib and re-run
Refered here