[アーキテクチャ]MVVM
MVVM?
Model
データ構造と処理
View
画面表示とユーザーインタラクションを担当
ViewModel
ビューの抽象化;データをビューに変換する
ビジネスロジックは依然としてViewModelが担当しています.
ただ論理的な観点がデータ中心に移った点には大きな違いがある.
ビューとViewModelの依存性を解消します.
また、データバインドとコマンドモードの使用にも注意してください.
インプリメンテーション
以前MVC記事で実現した機能をMVVMに変換する.
実際の動作結果はMVCと同じであるが,内部の実現差を見るためである.
IOSでは、MVVMは少し異質な感じがします.
概念的には、ビューの機能がViewとViewコントローラに分かれているためです.
SWIFTUIを使用する場合、MVVMのメリットは明らかになるはずです.
Model
struct Repository: Codable {
let id: Int
let node_id: String
let full_name: String
let description: String?
let url: String
let html_url: String
let created_at: String
let updated_at: String
}
struct SearchResponse: Codable {
var total_count: Int = 0
var incomplete_results: Bool = false
var items: [Repository] = []
}
View
class SearchTableViewCell: UITableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
func setData(data: Repository) {
nameLabel.text = data.full_name
descriptionLabel.text = data.description
}
}
ここで、ViewControlはViewカテゴリに相当します.ViewControllerは、ViewModelに関する情報を持っていますが、Input、Outputプロトコルで定義されているものに限ります.
依存注入に変更することもできます.
class SearchViewController: UIViewController {
var viewModel: (SearchViewModelInput & SearchViewModelOutput) = SearchViewModel()
}
イベント発生時に対応するビジネスロジックを呼び出すことをビューで実現します.制御ロジックの位置はViewControlからViewModelに移動します.
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.viewModel.fetchRepositories(text: searchBar.text)
}
データバインディングはKVO,Notification,Rx,Combineなどで実現できる.ここではCombineを使いました.
self.viewModel.repositoriesPublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] repositories in
self?.displayedRepositories = repositories
self?.tableView.reloadData()
}.store(in: &cancelBag)
ViewModel
データのクエリー、管理などのロジックを実現します.
ViewModelは自分のビューを参照する存在を知らない.
class SearchViewModel: SearchViewModelProtocol {
@Published var repositories: [Repository] = []
var repositoriesPublisher: Published<[Repository]>.Publisher { $repositories }
var cancelBag = Set<AnyCancellable>()
func fetchRepositories(text: String?) {
var urlComponents = URLComponents(string: "https://api.github.com/search/repositories")
urlComponents?.queryItems = [
URLQueryItem(name: "q", value: text)
]
URLSession.shared.dataTaskPublisher(for: (urlComponents?.url)!)
.map { $0.data }
.decode(type: SearchResponse.self, decoder: JSONDecoder())
.map { $0.items }
.replaceError(with: [])
.assign(to: \.repositories, on: self)
.store(in: &cancelBag)
}
}
結果
完全なコードは羽状バニラにあります.
Reference
この問題について([アーキテクチャ]MVVM), 我々は、より多くの情報をここで見つけました https://velog.io/@hanchi0/아키텍처-MVVMテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol