-1

I'm working through a tutorial and I noticed that when downcasting I didn't have to use an initializer method of the object. Is the object initialized? In the AppDelegate codebase below, I'm referring to the ItemsTableViewController. All I had to do was say "as!" but didn't need to use an init method or double parenthesis like this "ItemsTableViewController()".

Is the ItemsTableViewController initialized and if so how?

//
//  AppDelegate.swift
//  HomepwnerThirdTime
//
//  Created by Laurence Wingo on 4/26/18.
//  Copyright © 2018 Laurence Wingo. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        //create an ItemStore when the application launches
        let itemStore = ItemStore()

        //create an ItemsTableViewController
        //set the window property which is of type UIWindow from the UIApplicationDelegate protocol and downcast this property to an initialized ItemsTableViewController by using as!
        let itemsController = window!.rootViewController as! ItemsTableViewController
        //now access the ItemsTableViewController and set its itemStore property since it is unwrapped in the ItemsTableViewController which needs to be set
        itemsController.itemStore = itemStore
        //we just set the itemStore property of the ItemsTableViewController!  Yayy, WHEW!! Now when the ItemsTableViewController is accessed with that unwrapped ItemStore object then it will be set!!! WHHHHEEEEWWWWW!
        return true
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Laurence Wingo
  • 3,912
  • 7
  • 33
  • 61

2 Answers2

1

Casting and initialization have nothing to do with each other.

A cast is simply a way to tell the compiler: "Trust me, even though you think this object is one type, I know it really is another type".

Initialization is of course the creation of a new object.

In your code, your view controller has already been created for you through your storyboard. Your code is simply accessing this already created view controller. The cast is you telling the compiler that the rootViewController is actually an instance of ItemsTableViewController and not a plain old UIViewController.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • INTERESTING! So is it safe to say that since my appDelegate class has a property called window of type UIWindow, then the rootViewController property of this UIWindow instance is already initialized however was set to nil until I instructed it otherwise? – Laurence Wingo Apr 29 '18 at 15:32
  • 1
    Assuming you have a default app with a main storyboard, the storyboard is creating and setting up the `window` and its `rootViewController`. That is all done by the time the `didFinishLaunchingWithOptions` is called. Your code is not doing any initialization (other than the item store). You are accessing what was initialized for you by the storyboard. – rmaddy Apr 29 '18 at 15:35
  • but isn't the storyboard property an attribute of UIViewController and not an attribute of the appDelegate? – Laurence Wingo Apr 29 '18 at 15:40
  • The storyboard isn't a property or an attribute of either `UIViewController` or the app delegate. – rmaddy Apr 29 '18 at 16:00
  • The UIViewController reference doc says var storyboard under the area that says "Interacting with Storyboards and Segues". https://developer.apple.com/documentation/uikit/uiviewcontroller – Laurence Wingo Apr 29 '18 at 18:03
  • what am I saying incorrectly or not comprehending in this regard? – Laurence Wingo Apr 29 '18 at 18:06
1

rootViewController sure is initialised. If it is not then it would have been nil, and casting it using as! would have caused an error. Here, by downcasting, you are not doing anything to the VC object. You are just telling Swift that "yes I'm sure this will be a ItemsTableViewController by the time the code is run, so don't worry about it".

How is the VC initialised then?

This has to do with how iOS handles the launching of an app. When you tap on an app, it opens and a UIWindow is created. Then the first VC in your storyboard is initialised and set as the rootViewController of the UIWindow. After doing all of that, your app delegate is called.

Note that when you are in the didFinishLaunching method, it's just that the VC has been created. The views in the VC are not loaded. That's what viewDidLoad is for.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Hmmm...you stated that I'm telling Swift "yes I'm sure this will be a ItemsTableViewController" by the time the code is run, so don't worry about it." How do I really know this for sure? Or what did I do to make this assumption 100% legit? – Laurence Wingo Apr 29 '18 at 15:36
  • 1
    Look in your Storyboard. The initial ViewController (the one with the arrow pointing to it) had better be an `ItemsTableViewController` or this *will crash* at runtime. – vacawama Apr 29 '18 at 15:39
  • 1
    @CosmicArrows If you want to avoid a crash, you can use `as?` instead of `as!`, which evaluates to `nil` if it fails to convert the type. You can then use optional binding to do something else if the conversion fails. – Sweeper Apr 29 '18 at 15:41
  • 1
    @Sweeper You want it to crash when using `as!` in this case because if the root controller isn't really an `ItemsTableViewController` then you want to know right away during development so you can fix the problem with the storyboard. – rmaddy Apr 29 '18 at 16:01