【问题标题】:Why should the app delegate create instances for properties used in other viewControllers?为什么应用程序委托要为其他视图控制器中使用的属性创建实例?
【发布时间】:2018-03-31 20:48:06
【问题描述】:

我正在学习 Big Nerd Ranch 的 iOS 编程书中的 UITableView 教程。在本教程中,我们将一个新属性分配给 UIViewController,如下所示:

class ItemsViewController: UITableViewController {

    var itemStore: ItemStore!  

}

但是,在应用程序的 AppDelegate 中,我们在 AppDelegate 中实例化了这个 itemStore 属性,如下所示:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.


        let itemStore = ItemStore()


        let itemsController = window?.rootViewController as! ItemsViewController

        itemsController.itemStore = itemStore

        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


}

我的问题是,为什么应用程序委托要为其他视图控制器中使用的属性创建实例?这个属性是否应该在实际使用它的 viewController 中实例化,或者通过这种方式实例化,itemStore 对象在应用程序的持续时间内保持活动状态?

【问题讨论】:

  • 本书中有介绍。第 10 章:授予控制器对商店的访问权限。

标签: ios swift objectinstantiation


【解决方案1】:

这样做是为了使ItemsViewController 更可重用。 ItemsViewController 不需要知道 ItemStore 对象的详细信息,包括要实例化哪个 ItemStore 子类。它只需要知道该对象所遵循的接口。通过在外部设置ItemStore,ItemsViewController 可以很容易地与ItemStore 的其他子类一起使用,而无需更改。

这在第 10 章,在 iOS Programming: The Big Nerd Ranch Guide, 6th Edition 一书的 Giving the Controller Access to Store 部分中进行了介绍。

【讨论】:

    【解决方案2】:

    无论这是否是 Big Nerd Ranch 的意图,将 ItemStore 实例传递到视图控制器的最佳原因是为了可测试性。这种模式称为依赖注入。

    这个想法是您可以在单元测试期间向您的视图控制器提供模拟的ItemStore。 (这假设您进行单元测试,您应该这样做!:)

    通过模拟,您可以模拟您的视图控制器在 ItemStore 为 nil、空或包含某些项目时的行为。

    【讨论】:

      【解决方案3】:

      像这样声明itemStore并不意味着它会保留应用程序生命,它是didFinishLaunchingWithOptions内部的一个局部变量,如果它可以在ItemsViewController内部初始化,这种类外初始化样式是没有用的,可能是因为数据逻辑在 Appdelegate 内部,总是与 coredata 一起发生,或者它的项目将从launchingOptions 的本地/远程通知单击初始化

      【讨论】:

      • 不,这种初始化方式不是没用的。这称为依赖注入,非常有用。
      • 如果你读了剩下的我说“如果变量可以在类中初始化”
      • 我当然读过。你是说如果一个类可以初始化一个变量,它应该总是这样做。依赖注入表示为了可测试性,最好将某些类型的依赖传递到类中。
      • OP 询问为什么我们将 var 从类中初始化,答案正如我所解释的那样,因为如果我们想将数据传递给该类,并使用从类外的推送或数据源配置的特定 var否则,如果数据是静态的,它将无用
      • 你听说过依赖注入吗?
      【解决方案4】:

      在ItemsViewController类中,itemStore被定义为

      var itemStore: ItemStore!
      

      这里的itemStore 是一个未包装的变量。 所以它不接受nil 值。否则会导致运行时崩溃。意外nil。

      这就是为什么在AppDelegate 中我们需要确保itemStore 对象不是nil

      let itemStore = ItemStore()
      let itemsController = window?.rootViewController as! ItemsViewController
      itemsController.itemStore = itemStore
      

      【讨论】:

      • 这就引出了一个问题,为什么 itemStore 被定义为一个隐式展开的变量?
      • 它可能是ItemsViewController 类中的强制元素。
      • 那么,回到 OP 最初的问题,为什么不在视图控制器而不是 AppDelegate 中实例化它?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-16
      • 1970-01-01
      相关资源
      最近更新 更多