首页 > 解决方案 > Swift 中的泛型和 ViewModel

问题描述

我正在尝试使用泛型简化以下代码。除了对 ChildViewOne、ChildViewTwo 和 ChildViewThree 中的每个类型进行条件解包之外,我可以使用泛型实现相同的效果吗?

struct UserInfo {
  let name: String
  let image: UIImage
}

enum SomeType {
  case typeOne
  case typeTwo
  case typeThree
}

struct ParentViewModel {
   let userInfo: UserInfo
   let type: SomeType

   var contentViewModel: Any {
    switch type {
      case .typeOne:
           return ChildViewModelOne(name: userInfo.name, type: type)
      case .typeTwo:
           return ChildViewModelTwo(image: userInfo.image, type: type)
      case .typeThree:
           return ChildViewModelThree(image: userInfo.image)
   }
}

struct ChildViewModelOne {
  let name: String
  let type: SomeType
}

struct ChildViewModelTwo {
  let image: UIImage
  let type: SomeType
}

struct ChildViewModelThree {
  let image: UIImage
}

ParentViewController 将被注入 ParentViewModel。

class ParentViewController: UIViewController {
  let viewModel: ParentViewModel

  init(viewModel: ParentViewModel) {
    self.viewModel = viewModel
    super.init(bundle: nil, frame: nil)
  }

  // other required initializer

  func configureViewForType() {
     // Logic to handle subviews - ChildViewOne, ChildViewTwo & ChildViewThree
  }
}

这是我到目前为止所尝试的:我介绍了一个协议 ConfigurableView

protocol ConfigurableView {
    associatedtype ViewModel
    func configure(model: ViewModel)
}

class ChildViewOne: UIView, ConfigurableView {
    func configure(model: ChildViewModelOne) {

    }

    typealias ViewModel = ChildViewModelOne
}

更新

如何从 ParentViewModel 将其作为 ParentViewModel 中的contentViewModel对象返回?contentViewModel将根据ParentViewModel 中的值从内部调用,我加载了正确func configureViewForType()ParentViewControllertypeChildView

有没有更好的方法来实现这一目标?

标签: iosswiftgenerics

解决方案


视图模型实际上不是“视图模型”。这个想法很普遍,因为并非所有语言都有嵌套类型。相反,它是一个View.Model.

class ChildViewOne: UIView {
  struct Model {
    let name: String
  }

  init?(model: Model, coder: NSCoder) {
    self.model = model
    super.init(coder: coder)
  }

  private let model: Model

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

推荐阅读