Swift - 接收 json 对象作为视图控制器的输入参数?

问题描述

我正在为 iOS 项目做作业,其中一项业务逻辑规则是让视图控制器接收 id 作为输入参数,但我不明白意味着。

id一个 JSON 对象字段,如下所示:

{
"id": 1213213,"anotherKey:12322123,"andAnotherKey: {
"keyInKey":123121
},...
}

我的猜测是打开一个带有自定义初始化的视图控制器,如下所示:

    init(id: String) {
        
        super.init(nibName: nil,bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

我的理解可能是作业的意图吗?如果是这样,我如何从 SceneDelegate 实例化这个视图控制器?我采用了 MVVM 模式,场景委托看起来不是离开视图模型的好地方。任何建议将不胜感激!

解决方法

我的理解可能是作业的意图吗?

没有。如果您使用的是 MVVM,我宁愿将字符串值设置为 viewModel,并将完全配置的 viewModel 作为对 ViewController 的依赖注入(称为控制反转原则 (IoC))。

如果您不使用任何第三方依赖注入器,您可以始终使用 init 这称为通过构造函数的依赖注入

有多种方法可以引入依赖注入,讨论这些不在本答案的范围内。

下面的回答假设您没有使用任何第三方依赖注入器,而是使用基于 Constructor 的注入。

如何从 SceneDelegate 实例化这个视图控制器?

第 1 步:有一个 viewModel 类

class ViewModelA {
    let someParam: String

    init(with param: String) {
        self.someParam = param
        //rest of code
    }
    //rest of code whatever makes sense here
    //modification of string any buisness logic
    //or hold other data models
}

第 2 步: 将 ViewModel 作为构造函数依赖注入到 ViewController

class ViewControllerA: UIViewController {
    let viewModel: ViewModelA

    init(with viewModel: ViewModelA) {
        self.viewModel = viewModel
        super.init(nibName: nil,bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    //rest of code to set up,update UI and view delegates
}

步骤 3: 在 SceneDelegate 的 willConnectTo session 方法中将您的视图控制器设置为窗口的根视图控制器

    func scene(_ scene: UIScene,willConnectTo session: UISceneSession,options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard,the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)
        let viewModelA = ViewModelA(with: "abcd")
        let viewControllerA = ViewControllerA(with: viewModelA)
        window.rootViewController = viewControllerA
        self.window = window
        window.makeKeyAndVisible()
    }

我采用了 MVVM 模式,场景委托看起来不像 离开视图模型的好地方。

你必须在某处设置 rootView 控制器,你不觉得吗?之前我们曾经在 AppDelegate 中设置 rootView 控制器(从概念上讲,在 AppDelegate 中创建一个 ViewModel 和 ViewController 实例也有些片面)。即使你使用 storyboard 并将一些视图控制器设置为初始视图控制器,甚至 iOS 也在幕后做同样的事情。因为您想遵循 MVVM 而不是 MVC,所以您必须手动拦截和实例化 ViewController 并使用 viewModel 作为其依赖项。

我个人更喜欢使用带有路由器的 MVVM,这样可以分离创建和注入对 ViewController 的依赖(更好的关注点分离)并且可以重用(更好的代码重用性)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...