swift中使用MVVM架构更新数据



我正在使用MVVM架构来开发一个用于学习的小型天气应用程序。

<<h3>视图/h3>
class ViewController: UIViewController {

private var cityDataViewModel = CityDataViewModel()
private var data = [ConsolidatedWeather]()

@IBOutlet weak var label1: UILabel!

@IBOutlet weak var label2: UILabel!

override func viewDidLoad() {
super.viewDidLoad()
loadCityData()


}

func loadCityData(){
print("loadCityData")
cityDataViewModel.getCityData {
}
}
}

ViewModel

class CityDataViewModel{
private var networkManager = CityNetworkManager()

private var weatherNetworkManager = WeatherNetworkManager()
var weatherModel = [ConsolidatedWeather]()

var myStruct :[WeatherModel] = []

var weatherState: String?
var minTemp: Double?
var maxTemp: Double?
var currentTemperature: Double?
var summary: String?
var dateString: String = ""

//MARK: - Get cityInformation
func getCityData(completion: @escaping () -> ()) {
networkManager.getCityDataNetworkCall { [weak self](result) in
switch result{
case .success(let information):
information.forEach { (data) in
print("(data.title) || (data.locationType) || (data.woeid) || (data.lattLong)")
print("loadCityData 3")
self?.getCityWeatherInformation(with: data.woeid)
print("loadCityData 4")
}
completion()
case .failure(let error):
print(error)
}
}
}

//MARK: - Get Weather data
func getCityWeatherInformation(with woeid: Int){
//[weak self]
weatherNetworkManager.getWeatherDataNetworkCall(cityId: woeid) {[weak self] (result) in
print("loadCityData 5")
switch result{
case .success(let listOfData):
self?.weatherModel = listOfData.consolidatedWeather    
}
case .failure(let error):
print(error)
}
}
}

var ttile: String{
return weatherState ?? ""
}   
}
  • 从视图中,我正在发送一个调用ViewModel通过使用func getCityDat()
  • 来获取cityId
  • 在获得cityId后,我调用func getCityWeatherInformation(with woeid: Int)以获得详细的天气数据。我成功地从服务器获取了这些数据。

我如何将该信息发送到view以更新我的viewController?

建立评论中提到的协议/闭包系统当然是一个流行的选择。

从iOS 13开始,你还可以选择使用Combine来发布ViewModel上的更改,这可以触发ViewController更新。

一个简化的例子:

import Combine
import UIKit

class MyVC : UIViewController {
private var label = UILabel()
private var label2 = UILabel()
private var viewModel = ViewModel()
private var cancellables = Set<AnyCancellable>()

override func viewDidLoad() {
addLabels()
linkPublishers()
viewModel.getData()
}

func linkPublishers() {
//OPTION 1

viewModel.objectWillChange.sink { (_) in
DispatchQueue.main.async {
self.label.text = self.viewModel.text1
self.label2.text = self.viewModel.text2
}
}
.store(in: &cancellables)

// **** OR ****

//OPTION 2
viewModel
.$text1
.receive(on: RunLoop.main)
.sink { (newLabelText) in
self.label.text = newLabelText
}.store(in: &cancellables)

viewModel
.$text2
.receive(on: RunLoop.main)
.sink { (newLabelText) in
self.label2.text = newLabelText
}.store(in: &cancellables)
}

func addLabels() {
label.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
self.view.addSubview(label)
label2.frame = CGRect(x: 0, y: 40, width: 200, height: 40)
self.view.addSubview(label2)
}
}
class ViewModel : ObservableObject {
@Published var text1 = ""
@Published var text2 = ""

func getData() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.text1 = "Hello, world"
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.text2 = "Hello, world 2"
}
}
}

ViewModel在这里做了一个模拟异步网络调用的假任务。然后,它将其中一个@Published属性设置为该数据的结果。

回到ViewController,linkPublishers有两种不同的方式来连接这些已发布的属性:

  1. 观察objectWillChange,它在任何之前被触发已发布的属性更新
  2. 独立观察每个@Published属性

相关内容

  • 没有找到相关文章

最新更新