我正在尝试从MVC创建MVVM,但是我不能通过prepare传输之前可以传输的信息。原因是什么?我如何修复?
MainViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail", let detailVC = segue.destination as? DetailViewController, let indexPath = tableView.indexPathForSelectedRow {
let pokemon = viewModel.pokemons[indexPath.row]
detailVC.viewModel?.pokemonId = "\(indexPath.row + 1)"
detailVC.viewModel?.name = pokemon.name
detailVC.viewModel?.imageURL = viewModel.getPokemonSpritesURL(for: indexPath.row)
}
}
DetailViewModel
class DetailViewModel {
// MARK: - Properties
var pokemonId: String
let apiService: PokeAPIService
var name: String?
var abilities: [Ability]?
var imageURL: URL?
// MARK: - Initializers
init(pokemonId: String, apiService: PokeAPIService) {
self.pokemonId = pokemonId
self.apiService = apiService
}
// MARK: - Public Methods
func fetchPokemonDetails(completion: @escaping () -> Void) {
apiService.getPokemon(by: pokemonId) { [weak self] response in
guard let self = self else { return }
self.name = response.name
self.abilities = response.abilities
if let urlString = response.sprites?.frontDefault {
self.imageURL = URL(string: urlString)
}
completion()
}
}
}
DetailViewController
var viewModel: DetailViewModel?
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var abilitiesNameLabel: UILabel!
@IBOutlet weak var abilitiesNameLabel2: UILabel!
// MARK: - Private Methods
func configureView() {
viewModel?.fetchPokemonDetails(completion: { [weak self] in
guard let self = self else { return }
DispatchQueue.main.async {
self.nameLabel.text = self.viewModel?.name
self.abilitiesNameLabel.text = self.viewModel?.abilities?[0].ability?.name
self.abilitiesNameLabel2.text = self.viewModel?.abilities?[1].ability?.name
if let imageURL = self.viewModel?.imageURL {
self.loadImage(from: imageURL)
}
}
})
}
func loadImage(from url: URL) {
URLSession.shared.dataTask(with: url) { [weak self] (data, response, error) in
guard let self = self, let data = data else { return }
DispatchQueue.main.async {
self.imageView.image = UIImage(data: data)
}
}.resume()
}
当我切换回MVC时,我没有任何问题。我找不到我做错了什么,似乎我错过了一些小东西,但我不能弄清楚。
2条答案
按热度按时间sf6xfgos1#
你的问题在这里
在这一步,
detailVC.viewModel
是nil
,设置为VM的一些属性没有任何结果。所以在这个方法中,你需要创建DetailViewModel
的示例,并使用所有必需的数据将其设置为detailVC
,如下所示:omqzjyyz2#
它不工作的原因是因为MVVM结构可能不正确。在MVVM中,您不需要使用prepare方法。相反,您可以使用Observable或合并模式。这些模式在值发生更改时通知View Controller。在View Controller中,您可以使用Binder将ViewModel的输出绑定到View的输入。这样,视图总是与最新的ViewModel数据保持同步。
你可以从这个链接学习MVVM(可观察模式):- [1]:https://www.youtube.com/watch?v=sLHVxnRS75w
你可以从这个链接学习MVVM(合并):-https://www.youtube.com/watch?v=30LapcVtyBQ
我本可以修改你的代码来使用MVVM设计模式,但我认为理解它是如何工作的对你来说很重要,这就是为什么我为你提供了这两个教程链接。
谢谢你!