I've read several of the suggested posts that were to help with this problem but could not find something for this particular issue.
I need to set a property on my controller, the book is saying to do so in the app delegate. In the previous assignment using a navbar, this worked:
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey : Any]?) -> Bool {
// Override point for customization after application launch.
// Create an ItemStore to hold list of items
let itemStore = ItemStore()
// Access the ItemsViewController and set its item store
let itemsController = window!.rootViewController as! ItemsViewController
itemsController.itemStore = itemStore
return true
}
However, creating a similar program I need to use tab bar but can't get it to work and keep running into the error stated above, on the let editcontroller = tabcontroller. - line
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Create an pindatabase
let pinDataBase = PinDatabase()
// Access the pairsViewController and set its database
let tabController = window!.rootViewController as! UITabBarController
// this edit controller line is where I am stuck
let editController = tabController.tabBar as! EditViewController
editController.pinDataBase = pinDataBase
return true
}
The error is:
fatal error: unexpectedly found nil while unwrapping an Optional value
The controller I'm trying to set the property on is not the root controller but the third tab if that helps.
Your issue is your attempt to cast the UITabBar to your EditViewController. You need to access the array of view controllers from the tab bar controller and access the one that is actually the EditViewController.
let editController = tabController.viewControllers[2] as! EditViewController
This will access the 3rd view controller and cast it as needed.
Related
Apparently I'll go full Ubuntu by the end of the week and bin my iPhone.
iOS13 has come to my Xcode and I can't find a way to split screen equally Master and Detail view. All tutorials and guides refers to a previous iOS.
The code I tried in my AppDelegate is:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let split = window?.rootViewController as? UISplitViewController {
split.delegate = self
split.preferredDisplayMode = .allVisible
split.maximumPrimaryColumnWidth = .greatestFiniteMagnitude
split.preferredPrimaryColumnWidthFraction = 0.5
}
return true
}
but the screen is still splitted 30-70 or whatever the default is.
Figure out in iOS13 is SceneDelegate responsible for UIWindow so the code above should go in the sceneDidBecomeActive function in the SceneDelegate.
I am trying to have my application open a different view controller based upon whether an array is empty in the user's NSUserDefaults. Essentially, if the user has previously saved data in the app, the app will open up to where they can select the data. Otherwise, the app will open to a welcome screen.
However, when the array is empty, I see the background color that I set for the welcome screen, but not the text or button that I laid out in the storyboard. When the array is not empty and the data page should open, my app crashes with a SIGABRT error. I checked all of the outlets for the view controller in question and nothing seems to be disconnected. Additionally, when I comment out the code in the app delegate and set the data view controller as my initial starting view, the app runs fine.
The full error is "Thread 1: signal SIGABRT" and it is tagged in the class AppDelegate line.
The code I used in the App Delegate is below:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
var accounts = loadAccounts()!
if accounts.isEmpty {
let welcomeController = WelcomeViewController()
self.window!.rootViewController = welcomeController
} else {
let tableController = AccountTableViewController()
self.window!.rootViewController = tableController
}
return true
}
func loadAccounts() -> [Account]? {
return NSKeyedUnarchiver.unarchiveObject(withFile: Account.ArchiveURL.path) as? [Account]
}
Maybe the UIWindow is not set properly.
let bounds = UIScreen.main.bounds
self.window = UIWindow(frame: bounds)
self.window?.rootViewController = `your view controller`
self.window?.makeKeyAndVisible()
What else can go wrong?
var accounts = loadAccounts()!
This line is the culprit for you. Precisely this symbol ! is I guess. You are trying to fetch data from a database or a filesystem and expect it will always be there.
Think about it, it can't be true all the time.
# check if account array is not empty; I would have returned nil if it would be empty and so we can avoid that extra check here.
if let accounts = loadAccounts(), !accounts.isEmpty {
let tableController = AccountTableViewController()
self.window!.rootViewController = tableController
return true
}
let welcomeController = WelcomeViewController()
self.window!.rootViewController = welcomeController
Also, if you can provide more info about the error message from your debug console. Then I would be able to help in a better way.
I have a custom tab bar controller. each tab contains a viewcontroller embedded in a navigation controller. I get a value for pro_user from the database in appledelegate and set it there. then before CustomTabBarController gets launched (in appledelegate), i set it's "pro_user" property to true or false (this works and CustomTabBarController receives the value from appledelegate).
Now i'm trying to pass this same value to the ViewControllers (ViewController1 and ViewController2). each view controller also has a "pro_user" property.I'm doing this by creating the viewcontroller instances and then setting their pro_user property before embedding each viewcontroller in a navigationcontroller. but neither viewcontroller is actually receiving the value of pro_user which i'm setting in CustomTabBarController. I hope this is clear. How do i pass the value of pro_user from CustomTabBarController to each of the view controllers? programmatically (i'm not using storyboards)
class AppDelegate: UIResponder, UIApplicationDelegate {
var pro_user = true
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
[UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame:UIScreen.main.bounds)
window?.makeKeyAndVisible()
let customTabBarController = CustomTabBarController()
customTabBarontroller.pro_user = pro_user
self.window?.rootViewController = customTabBarController
return true
}
}
class CustomTabBarController:UITabBarController{
var pro_user : Bool?
override func viewDidLoad(){
super.viewDidLoad()
let viewController1 = ViewController1()
viewController1.pro_user = pro_user //doesn't work
let firstNavigationController = UINavigationController(rootViewController: viewController1)
let viewController2 = ViewController2()
viewController2.pro_user = pro_user //doesn't work
let secondNavigationController = UINavigationController(rootViewController:viewController2)
viewControllers=[firstNavigationController,secondNavigationController]
}
It looks like you're setting a global setting. If so you may want to consider using UserDefaults.
E.g. with a nice extension:
extension UserDefaults {
var isProUser: Bool {
get {
return bool(forKey: "isProUser")
}
set {
set(newValue, forKey: "isProUser")
}
}
}
Then anywhere in your app you can set it:
UserDefaults.standard.isProUser = true
And get it:
let isProUser = UserDefaults.standard.isProUser
The value is also saved between launches.
I currently have the application set up with a UINavigationController as the initial view, which has a UITableViewController as its root view controller. The app runs fine up until this point. I have the following code in AppDelegate.swift:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let favLibrary = FavLibrary()
let navController = window!.rootViewController as! UINavigationController
let favController = navController.topViewController as! FLViewController
favController.favLibrary = favLibrary
return true
}
I am trying to implement a UITabBarController so that I can switch between two UITableViewControllers at the same level (Favorites and a Library) using the Tab Bar.
I embed each VC in its own Navigation Controller, then I embed the two Navigation controllers into one Tab Bar Controller.
Upon running the application, it crashes with the following error:
Could not cast value of type 'UITabBarController' (0x115f9e430) to 'UINavigationController' (0x115f971d0).
2018-09-27 15:49:43.811377-0700 appName [3675:954448] Could not cast value of type 'UITabBarController' (0x115f9e430) to 'UINavigationController' (0x115f971d0).
How can I correct the code in AppDelegate to retain functionality with the new arrangement of Tab Bar and Navigation Controllers?
If I understand your question correctly, I suppose you should access the tabBarController first, then retrieve the view controllers it contains, which should be a list of navigation controllers. Then you can get your view controller inside the selected navigation controller:
let tabBar = window!.rootViewController as! UITabBarController
let targetTabNav = tabBar.viewControllers![1] as! UINavigationController // change index to what you want
let targetVc = targetTabNav.viewControllers.first!
// Do what you want with the target Vc ...
I have created a view controller in didFinishLaunching method of AppDelegate and assigning it to window's root view controller.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds) // issue with allocating UIWindow
self.viewController = AKSidePanelController()
self.viewController!.centerPanel = UINavigationController(rootViewController: UIStoryboard.centerViewController()!)
window!.rootViewController = self.viewController
window!.makeKeyAndVisible()
return true
}
func shouldAutorotate() -> Bool {
return true
}
func supportedInterfaceOrientations() -> Int {
return UIInterfaceOrientation.Portrait.rawValue | UIInterfaceOrientation.LandscapeLeft.rawValue | UIInterfaceOrientation.LandscapeRight.rawValue
}
for some reasons, auto rotation is not working. i think the problem is because of allocating window in didfinishlaunching. When i try to launch directly from storyboard(by marking isInitialViewController = yes) without adding any code on didFinishLaunching, autorotation works. As you can see, i need to load "viewController" as rootviewcontroller. What i am doing wrong?
I am using Xcode 6.1
The problem is that i am loading View from storyboard as well as initialising view controller in didFinishLaunchingOption in App delegate. the solution is to avoid loading initial View from storyboard.
Set IsinitialViewController to no and load the view controller from appdelegate
This one helps me to fix the issue. Programmatically set the initial view controller using Storyboards
Note that you have to make "Main storyboard file base name" as empty in plist.