Group Group Group Group Group Group Group Group Group

Chapter 32: Window variable is now in Scene rather than app delegate file

While working on chapter 32, I noticed that the window variable was moved to the scene file rather than the AppDelegate file. If I forcefully added a UIWindow variable in AppDelegate, it would crash right after attempting to cast it as a UITabBarController since the window variable seems to be nil

2 Likes

I’m having the same problem and cannot more forward. I’ve tried replacing code from the finished project and it doesn’t correct the error. Also tried to delete the scenedelegate… Not sure what direction to take this one

@george_solorio @razmanugget What error do you get exactly?

The error is:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

It appears on the line: let tabController = window!.rootViewController as! UITabBarController

The program builds successfully, but then crashes when nil is found.

If you deleted your scene delegate put it back to your project. Can’t find it in Bin? Create new single app project and copy it from there to your MyLocation project.

Now follow this steps to achieve same thing as shown in the book for AppDelegate.swift file.

  1. Open SceneDelegate.swift file in Editor.

  2. At the top just after import UIKit add import CoreData

  3. Then put this properties just under the window property or cut and copy them from AppDelegate.swift file if you already have them there:

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "DataModel")
    container.loadPersistentStores { (storeDescription, error) in
        if let error = error {
            fatalError("Could not load data store: \(error)")
        }
    }
    return container
}()

lazy var managedObjectContext: NSManagedObjectContext =  persistentContainer.viewContext
  1. Find scene(_:willConnectTo:options:) method. Usually is the first method. Just after guard let _ = (scene as? UIWindowScene) else { return } put this code in or cut and copy it from AppDelegate.swift file if you already have it there:
let tabController = window!.rootViewController as! UITabBarController

if let tabViewController = tabController.viewControllers {
    let navController = tabViewController[0] as! UINavigationController
    let controller = navController.viewControllers.first as! CurrentLocationViewController
    controller.managedObject = managedObjectContext
}

And make sure that your Main storyboard view controller hierarchy looks like this:

3 Likes

Thank you for helping me with this.
I added your changes from above and I now have 2 new errors -> both referencing the line
controller.managedObject = managedObjectContext

the error is -> value of type ‘CurrentLocationVC’ has no member ‘managedObject’

I still have the unexpectedly found ‘nil’ while upwrapping error.

I should have mentioned this earlier, but didn’t think it would make a difference. I abbreviate ViewController in my files as VC. I don’t do this for any Apple created VC’s (ie. UITableViewController). I started doing this a little while back because I think it makes the code cleaner and easier to read. Maybe this is the first time it could be the reason for my errors… Anyway, this VC abbreviation is only used for: CurrentLocationVC, LocationDetailsVC, and CategoryPickerVC

Okay, thank you again for trying to help.

Does your CurrentLocationVC class contain managedObjectContext property? Check that this managedObjectContext property is not declared as private. Please provide your code so I can look at it or upload project on GitHub and share project link.

Hello interactivexr,
Thank you looking into this. I looked again to find I was using managedObject instead of managedObjectContext. Changed it back and that fixed the additional error.

Still have the Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value error though.

My github is: https://github.com/razmanugget and I’ve pinned the iOS Apprentice book to the top.

did you manage to solve it? i just encountered the same error

No, I never resolved this issue. I’ve spent about 6 hours checking all the connections between storyboards and controllers and checking the code against the version in the book example which works fine.

When I drop the book example code in, it still gives me the “nil” error, so I am pretty sure I don’t have an error in my code. I think I missed hooking up something, but I can’t find it.

Finally I went on to the next lesson and had an error there too toward the end. I think the errors are most likely on my end (but maybe not), but I also think the book should be a little more clear about code changes which need to occur. For example, if there is new code or a code change, then it should always appear in its own box. Usually this is the case, but sometimes the code change is buried in a paragraph and you have to be reading carefully in order to not miss it.

the solution for scene delegate worked for me at that point, but in the next chapter it doesnt…
any other solution??

@razmanugget your AppDelegate.swift file still includes code that must be deleted from there. I said that you must cut and copy code to SceneDelegate.swift file if you already have it in AppDelegate.swift file. Read carefully and repeat steps above. The reason that you get Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value error is because you accessing window property of AppDelegate.swift file which will always be nil. Property window was moved to SceneDelegate.swift file and it isn’t accessible in AppDelegate.swift file anymore. This change happened when Xcode 11 and iOS 13 was released. If you are writing application in Xcode 11 or later you can find window property in SceneDelegate.swift file. So don’t try to declare window property in AppDelegate.swift file on your own because it will always be nil(if you don’t assign value to it of course).

You have saveContext() method in AppDelegate.swift file which depends on persistentContainer variable but it isn’t part of the book, so I won’t help you with that. You can leave persistentContainer and and managedObjectContext variables in AppDelegate.swift file in order for your saveContext() method to work properly.

FIX:
To get your application working and get rid of Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value error just change application(_:didFinishLaunchingWithOptions:) method in AppDelegate.swift file to return true as it was in first place and remove window property because you don’t want to access it as explained above.

@saipurva can you be more specific at which point in next chapter your code stops working?

i got it solved. thank you :slight_smile:
i figured it was a tiny error. that i guess it often happens while coding

1 Like

Thank you again for trying to help me. New error with the line change to controller.manageObject = managedObjectContext

Should that read - controller.manageObjectContext = managedObjectContext

I already have return true in the func application didFinishLaunchingWithOptions… I’m just not following this. Sorry. I’ll try it again when the next book is released. Maybe it will be easier then :slight_smile:

Your method application(_:didFinishLaunchingWithOptions:) should be like this and nothing else:

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
         return true
   }

You can add persistentContainer and managedObjectContext variables back to AppDelegate in order for your saveContext() method to work.

I changed it to return true, then wiped out saveContext… and the app runs again, but without the save functionality. That’s fine. Let’s just leave it here. Thank you for all of your help

Hey are you guys planning to share an official fix to this? Is this caused by the new SceneDelegate.swift file?
Thanks for all your help!

This fix worked for me. Thank you for sharing!