I'm trying to instantiate a UINavigationController with a rootViewController in my AppDelegate. I've looked on this website, but all the examples were from Objective-C or used storyboards (which I'm trying to get away from). 'HomeScreenController` is the root view of the application.
Edit: this shows up in the console
2015-07-18 14:42:25.376 FastFactsSwift[4749:343495] Failed to instantiate the default view controller for UIMainStoryboardFile 'Main'
- perhaps the designated entry point is not set?
How do I fix this?
The following code results in just a black screen:
AppDelegate.swift:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window?.rootViewController = UINavigationController(rootViewController: HomeScreenController())
return true
}
...
HomeScreenController.swift:
import UIKit
class HomeScreenController: UIViewController, UISearchBarDelegate, UITableViewDelegate{
override func viewDidLoad(){
super.viewDidLoad()
var width = self.view.viewWidth
var height = self.view.viewHeight
//Add stuff to the view
}
...
Why is HomeScreenController showing up as a black screen?
The problem was not configuring AppDelegate to not use a storyboard.
How do I create a new Swift project without using Storyboards?
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
A swift iOS app has 3 targets - AppTarget, Main (static lib which contains the entry point i.e. AppDelegate) and Presentation (static lib which contains UI code). AppTarget depends on Main and Presentation. Presentation depends on Main.
Question is, how do I set the UIWindow variable in Main from Presentation?
#main
public class AppDelegate: UIResponder, UIApplicationDelegate {
// UIWindow view of UIApplicationDelegate protocol
var window : UIWindow?
...
}
I tried two approaches:
Approach1:
Directly access the UIWindow variable using the AppDelegate object, but it gives 'Cannot assign to property: 'shared' is a get-only property' error:
UIApplication.shared.delegate?.window = UIWindow() // Error: Cannot assign to property: 'shared' is a get-only property
Approach2:
Use an intermediate static variable like:
// In AppDelegate,
static var keyWindow : UIWindow? = nil
public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Set UIWindow variable to the static instance.
window = AppDelegate.keyWindow
// Now, instantiating AppDelegate.keyWindow is the same as instantiating window (?).
...
return true
}
// Elsewhere, in Presentation,
func CreateWindow() {
window = AppDelegate.keyWindow
AppDelegate.keyWindow = UIWindow()
AppDelegate.keyWindow?.rootViewController = ViewController()
AppDelegate.keyWindow?.makeKeyAndVisible()
}
// ViewController has a simple UI
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemGreen
}
}
This gives me a black screen, meaning, there's no UI...an empty screen. But I expected to see a green screen.
I understand that UI has to be set in the UIWindow variable of the AppDelegate (if you use another UIwindow variable, its contents are not displayed and you'd get an empty black screen), due to its conformance to UIApplicationDelegate protocol.
How can I achieve this elegantly?
Note1: Assume I've opted out of scenes
Note2: Ignore how AppDelegate in Main invokes CreateWindow() in Presentation, but it somehow does.
What's the absolute bare minimum code to create a project that creates a UIView and shows it on the screen of an iOS device?
Without Storyboards, templates or any other contrivance. Just the barest presentation of a UIView.
I appreciate the templates are there to make things "easier", but for the sake of comprehending how everything works together, I'd like to try to conceive the frameworks and their relationships with the OS in the barest, truly code based form.
i.e. without Storyboards and all their processes. Just purely in code.
I've tried using google to find something with someone discussing iOS in an holistic manner, so as to view Views with clarity... but it's all about "ease" rather than understanding, so far as I can see.
With Swift.
// All puns were non-intential byproducts of irritation.
EDIT:::
How do I even start a new Project without a View Controller, Storyboard etc? There seems to be only storyboard based templates, and no way to start a "blank" project.
barest minimum would be this, just place this in your app delegate, delete the other .swift files, and this should be the barest you need:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var rootViewController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
rootViewController = UINavigationController(rootViewController: ViewController())
self.window!.rootViewController = rootViewController
self.window!.makeKeyAndVisible()
return true
}
}
this requires Zero storyboards, BUT if you want add a VIEW to all of this and have control over that uiview, then do this:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var rootViewController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
var firstVC = UIViewController()
var firstVCView = UIView()
firstVCView.backgroundColor = UIColor.redColor()
firstVC.view = firstVCView
rootViewController = UINavigationController(rootViewController: firstVC) self.window!.rootViewController = rootViewController
self.window!.makeKeyAndVisible()
return true
}
}
i can show you from the start, ill start a brand new project and strip it:
here's how:
select sinlge view application project
go into info.plist file, delete these two entries:
Then, delete the storyboard, and the nib.
Keep the "ViewController.swift" file
place this in your AppDelegate.swift:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var rootViewController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
rootViewController = UINavigationController(rootViewController: ViewController())
self.window!.rootViewController = rootViewController
self.window!.makeKeyAndVisible()
return true
}
}
then, do this, click no the button "use asset catalog"
the click on the pop up box that you want to use an asset catalog, then make sure this field is blank, where it says "launch screen file"
compile and run your project
A completely empty application with an app delegate, in didFinishLaunchingWithOptions this will present a view:
self.window.rootViewController = [UIViewController new];
there is a view in UIViewController
From my appdelegate I need to execute a method that is from a viewcontroller.
Please, can anybody tell me how to easily have the possibility to call whatever method I need from my appdelegate?
A lot of questions regarding this argument but none of these are useful/complete/right, so please avoid to post URL to other topics: I already checked all questions but I really can't find any precise answer regarding doing this in Swift. :)
It depends on how you've arranged your view controllers but here's an example from a simple iPhone master/detail project.
let root : UINavigationController = self.window!.rootViewController! as UINavigationController
let master : MasterViewController = root.topViewController as MasterViewController
println("\(master.description)")
The way I did it was to search for the view controller I want, starting on AppDelegate's var window: UIWindow? and then going deeper until I find it. I originally tried to implement NSNotification but this is not recommended on swift (I think computed property is a good replace for that, but it don't work in this case).
This is how I did for my tab based application with a NavigationController on top of my ViewController:
if let rootViewController = self.window?.rootViewController as? UITabBarController
if let viewControllers = rootViewController.viewControllers {
for navigationController in viewControllers {
if let yourViewController = navigationController.topViewController as? YourCustomViewController {
if yourViewController.hasSomeFlag {
yourViewController.theMethod()
}
break
}
}
}
}
You can do it with notifications, just add observer to your viewcontroller, post a notification from your app delegate, this observer will catch it and run a function you specify.
this tutorial should help get you started: https://www.codefellows.org/blog/how-to-implement-an-nsnotification-observer-in-swift
Try this
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
// Override point for customization after application launch.
return true
}
func customMethod()
{
}
}
Call custom method from ViewController
class ViewController: UIViewController {
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
appDelegate.customMethod()
}
I am trying to cast my window.rootViewController as a UIPageViewController but anytime I access the class property which I defined it blows up with swift dynamic cast failed. My storyboard has a UIPageViewController is the initial scene.
PageViewController is just a subclass of UIPageViewController
class AppDelegate: UIResponder, UIApplicationDelegate, UIPageViewControllerDataSource {
var window: UIWindow!
var pageViewController: PageViewController {
return window.rootViewController as PageViewController
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
pageViewController.dataSource = self
return true
}
}
The main issue actually was because I was subclassing UIPageViewController I had to add the custom class to the ViewController inside my storyboard. At first I figured that since PageViewController is a UIPageViewController, and I am just casting the rootViewController to a PageViewController, it should've of worked. By adding the custom class it fixed my problem.
I also tested by not subclassing, it worked with out specifying a custom class.