【问题标题】:Swift - receive json object as input parameter to view controller?Swift - 接收 json 对象作为视图控制器的输入参数?
【发布时间】:2021-04-24 09:41:00
【问题描述】:

我正在为 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 模式,场景委托看起来不是离开视图模型的好地方。任何建议将不胜感激!

【问题讨论】:

  • 请检查答案并让我知道它是否有帮助
  • @Sandeep 是的,我已经检查了你的答案,我需要一些时间来学习。这对我来说是一个非常新的概念。首先非常感谢您的详细回答。我会告诉你的!

标签: swift mvvm init input-parameters


【解决方案1】:

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

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

如果你不使用任何第三方依赖注入器,你总是可以使用init 这称为Dependency injection via Constructor

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

下面的答案假设您没有使用任何第三方依赖注入器并使用基于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
}

第二步:将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
}

第三步:在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 实例也有些不稳定)。即使您使用故事板并将某些视图控制器设置为初始视图控制器,即使 iOS 在后台也会做同样的事情。因为你想遵循 MVVM 而不是 MVC,你必须手动拦截和实例化 ViewController,并将 viewModel 作为其依赖项。

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

【讨论】:

  • 谢谢!我还在学习,但想问后续问题。如前所述,我必须在 SceneDelegate 中将 json 中的“id”输入到视图控制器的“构造函数”中,以实例化视图控制器。您的示例代码看起来很棒且鼓舞人心,但我仍然不知道如何完成这项工作。 (我正在尝试使用 RxSwift 并且我是一个非常初学者。所以无论是否使用 RxSwift,优先级是实现目标,RxSwift 是一个选项。)
  • @matthew-so:RxSwift 是一个 FRP(功能响应式编程范式),就像面向对象编程或面向协议编程一样,反应式编程只是另一种编程范式。您选择哪种编程范式不应该影响最终目标。它们只是实现最终目标的不同方式,同样不应该影响设计模式决策。虽然一种编码范式可能比其他的更倾向于一种设计模式,但无论如何它不会阻止你选择你想使用的任何设计模式
  • 我认为您有点困惑并且一次占用了太多概念,而是一次熟悉一个概念,看看它的实际实现,然后一旦您有了正确的想法,您就可以决定哪种编程范式选择n为什么?选择哪种设计模式,为什么?等等等等
  • 我有点困惑。由于“将 id 作为输入参数”,我感到非常困惑 :( 但您的解释很清楚且具有导航性。非常感谢!我想有时间思考为什么,但是作业有截止日期并且正在苦苦挣扎。希望准时弄清楚。再次非常感谢您的指导。这令人印象深刻。
  • @matthew-so:RxSwift 有一点指数学习曲线,如果您不熟悉任何类型的 Ractive Programming 范例(如果您以前从未使用过任何此类框架),请使用 Swift(其中是简单的面向协议的编程)并且只需坚持您所知道的任何更好的编码实践,主要坚持价值赛门铁克而不是参考赛门铁克,使用协议而不是继承,关注分离,依赖注入之类的东西
猜你喜欢
  • 2014-01-05
  • 2016-01-23
  • 2023-03-05
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-05
相关资源
最近更新 更多