最初に
昨日の記事でクラロワのトップ選手を持ってきましたが今回はMVPを意識しながら自分のユーザーデータをアプリに表示させるところまでやります。
次の記事
https://qiita.com/daichi77/items/f32e31df7b173422b5ed
今回やったこと
- MVPを意識しながらアプリを作る
- クラロワのAPI使って自分のアカウント情報を表示する。
妥協ポイント
- レイアウトのデザインは全く気にしない。
- 記事を二つに分ける。(今日はviewとpresenterの部分をやります。明日の記事にModel書きます。)
全体の大まかな流れ
- ViewからInputを通してPresenterの処理を呼びます。
- PresenterはModelなどの処理を読んだ後にOutputを通してViewの変更をします。
先ほども言いましたがこの記事ではViewとPresenterの大まかな流れだけやります。
Modelの部分は明日の記事でやります。
View
viewのファイルはこの二つです。
storyboradはただlabelを均等に配置してあるだけです。
続いてUserViewControllerです。
import Foundation
import UIKit
class UserViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var expLevelLabel: UILabel!
@IBOutlet weak var trophiesLabel: UILabel!
@IBOutlet weak var bestTrophiesLabel: UILabel!
private var presenter: UserPresenterInput!
override func viewDidLoad() {
super.viewDidLoad()
self.inject(presenter: UserPresenter(view: self))
self.presenter.fetchUsers()
}
func inject(presenter: UserPresenterInput){
self.presenter = presenter
}
}
//outputの部分、Presenterから呼ばれる。
extension UserViewController: UserPresenterOutput {
func updateUser(user: Player) {
//viewの処理なのでメインスレッドで
DispatchQueue.main.async {
self.nameLabel.text = user.name//ユーザーネームを代入
self.expLevelLabel.text = "ランク:\(String(user.expLevel))"//レベルをラベルに代入
self.trophiesLabel.text = "トロフィー:\(String(user.trophies))"//トロフィーをラベルに代入
self.bestTrophiesLabel.text = "最高トロフィー:\(String(user.bestTrophies))"//最高トロフィーをラベルに代入
}
}
}
}
viewControllerでやっていることは単純でPresenterの初期化とOutPutの処理の記述、inputの呼び出しです。
extension Protocolで切り分けることでOutputの部分を明確にしています。
オブザーバー同期だとOutputの部分が宣言的ものになります。
次にPresenterです。
Presenter
import Foundation
protocol UserPresenterOutput: AnyObject {
func updateUser(user: Player)
}
protocol UserPresenterInput {
func fetchUsers()
}
class UserPresenter: UserPresenterInput {
private weak var view: UserPresenterOutput?
init(view: UserPresenterOutput) {
self.view = view
}
func fetchUsers(){
let client = ClashRoyaleClient()
let request = ClashRoyaleAPI.SearchUser(keyword: "/#99V2VQUQ")
client.send(request: request) { result in
switch result {
case let .success(response):
self.view!.updateUser(user: response)
case let .failure(error):
print(error)
}
}
}
}
Presenterに書いてあるのはprotocolの定義とModelの処理を呼んでその結果次第でOutputを呼ぶInputの部分です。
ViewやPresenter次の記事で出てくるPresenterをProtocolで切り出すことで完全に疎結合にしてtestをしやすくしています。
Inputの部分ではModelのAPIを叩く処理を呼び出してその後にOutputを呼び出しています。
言い訳タイム
時間がなく忙しいのでModelの部分(APIを叩く部分)は明日書きます。
次の記事(Model編)
https://qiita.com/daichi77/items/f32e31df7b173422b5ed