【问题标题】:Create singleton of a viewcontroller in swift 3在 swift 3 中创建视图控制器的单例
【发布时间】:2021-01-25 19:08:44
【问题描述】:

我知道如何在 swift 中创建单例类。创建单例类的最佳且简单的方法如下:

class Singleton {
    static let sharedInstance = Singleton()
}

但我不需要任何普通课程的单身人士。我需要为视图控制器类创建单例。所以我使用这段代码创建单例

class AViewController:UIViewController {

    static let sharedInstance = AViewController()

    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

}

AViewController() 附近出现错误

Missing argument for parameter 'coder' in call

看起来它希望我用init(coder: NSCoder) 进行初始化。但是我应该通过coder传递什么参数或值?

【问题讨论】:

  • 你检查过class Singleton : NSObject这个吗?
  • 你为什么不把有问题的代码放在你的问题中?
  • required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
  • 'required public init?(coder aDecoder: NSCoder){ super.init(coder: aDecoder) }' 在你的代码中添加这个
  • 视图控制器通常不适合单例。如果你真的想这样做,我们可能需要更多地了解这个视图控制器的视图层次结构是如何创建的(故事板中的场景?NIB?以编程方式创建?)。但是,如果您有兴趣,您可能想解释一下为什么要使用单例,我们也许可以建议更好的模式。

标签: ios swift singleton viewcontroller


【解决方案1】:

如果你真的想为某个场景对应的视图控制器设置单例,你可能会这样做:

class SecondViewController: UIViewController {

    static let shared = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Foo")

}

在此示例中,情节提要为 Main.storyboard,相关场景的情节提要标识符为 Foo。显然,将这​​些值替换为适合您情况的任何值。

然后调用它的其他视图控制器可以执行以下操作:

@IBAction func didTapButton(_ sender: Any) {
    let controller = SecondViewController.shared
    show(controller, sender: self)
}

我不推荐视图控制器使用单例。视图控制器(及其视图)应在需要时创建,并在它们被解除时被释放。而且您正在失去许多故事板的好处(通过它您可以看到场景之间的逻辑流程以及它们之间的转场)。而且,如果您在不同的上下文中使用此视图控制器,您将引发由于视图控制器层次结构与视图层次结构不同步而产生的问题。我真的不鼓励您将单例用于视图控制器。

但如果你打算这样做,你可以做类似的事情......

【讨论】:

  • 我需要在UITabBarController 的 3 个选项卡中拥有相同的控制器/视图。我应该使用singleton 吗?还是建议为每个单独的实例?请分享您对此案例的建议。
  • 首先,我应该说我认为视图控制器一般来说对于单例来说是很差的用例。其次,如果您有三个选项卡,我假设每个选项卡都有一些不同(例如,即使视图控制器的类相同,也有不同的数据),所以我肯定会建议每个选项卡使用单独的实例。
  • 好的..谢谢您的回复,是的..我不得不使用单独的实例
  • @Rob:我使用了你的建议,效果很好。我的用例是我要去 ViewController A 等待建立连接。同时我可以返回或更改为另一个 ViewController。因此,当我回到 A 时,我将拥有一个新实例和所有新的中继订阅。所以我为我的 VC 考虑了单例。我现在没有看到任何不当行为,但我想避免它。我的应用程序将在 Apple Store 上架,所以我不希望他们因为不遵守标准而拒绝它。那么你有什么建议吗?
  • @msc87 1. Apple 不关心您在代码中使用的设计模式。他们只关心你做了什么,而不是你怎么做。 2.如果你想保持VC A活着,那并不一定意味着你需要跳转到单例模式。您只需要保留对它的引用。 3. 如果你试图保持正在进行的连接请求,这段代码无论如何都不属于视图控制器,所以问题不是真正保持 VC A 活着,而是网络层。我就是这样做的。但是,Apple 并不关心代码的优雅和漂亮的架构,所以随心所欲。
【解决方案2】:

尝试做:

AppDelegate:

添加对 ViewController 的引用,以便您可以全局访问它,如下所示:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    private var viewController: ViewController?

    func getViewController() -> ViewController {
        if viewController == nil {
            // make sure that the name of the storyboard is "Main"
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            // make sure that you named the viewcontroller in storyboard (Storyboard ID), it is the identifier
            viewController = storyboard.instantiateViewController(withIdentifier: "ViewControllerStoryboardID") as! ViewController
        }

        return viewController!
    }


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

    // ....
}

AnotherViewController(用法):

现在您可以通过“AppDelegate”访问它,如下所示:

class AnotherViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()


        let appDelegate = UIApplication.shared.delegate as! AppDelegate

        let vc = appDelegate.getViewController()
    }

    // ...
}

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    我会推荐类似的东西:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-28
      • 2017-07-24
      • 2017-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多