iOS 開発では、MVC アーキテクチャ モードではコントローラーが肥大化しすぎるため、現在は MVVM アーキテクチャ モードの方が一般的です。以下に、iOS での MVVM の実践について簡単に紹介します。
1.iOS MVVM
次の図は、コントローラーではなく、ディスプレイまたはシャットダウン コントローラー(コーディネーター)として参照されるMVVM-C
デザイン モードの構造図です。実際の開発では、でタスクを完了することが一般的であるため、ここではコーディネーターには注意を払いません。C
Coordinate
Controller
展示或者关闭控制器
1. 役割分担
比較するとMVC
、新しいモジュールが追加されておりVM
、各モジュールの役割は次のとおりです。
VM :との間のブリッジVM
であり、表示に一連のプロパティを提供します。プロパティには、変形を変換するときに表示に変換する必要がある値が含まれています。iOS では、通常、ネットワーク要求と更新も担当します。V
M
View
Model
View
Model
VC :VM
メディアの属性間のView
バインディング関係を確立する責任を負い、インタラクション イベント応答の特定のロジックを担当します。グラフ内のコーディネーターが確立されていない場合は、通常、ページのジャンプ ロジックが含まれます。
V : ビューの具体的な作成とユーザー インタラクションの監視、モデル内のデータのプレゼンテーション ロジック。
M : アプリケーションに必要なデータの保存と管理、および関連するビジネス ロジックの実行を担当します。V
またはVM
と控制器
組み合わせてはいけません。
RxSwift
2.バインディングのためのリアクティブプログラミング
- 上記は
VC
バインディング関係の確立を担当しており、それをKVO
達成するために使用できますが、データの変換や変換が必要な場合はさらに面倒なので、お勧めできません。これは、RxSwift
レスポンシブ プログラミングに特別に使用されるフレームワークのセットであり、多くの変換関連関数を提供し、バインディング関係をより適切に確立するのに役立ちます。 - を使用する
RxSwift
と、ニーズに応じて一方向または双方向のバインディングを実現でき、RxSwift
機能に習熟すると、コードの品質と利便性を向上させることができます。
2. レスポンシブプログラミングの例
RxSwift を使用して実装された単純なバインディングを次に示します。
var modelObject: ModelObject!
var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
modelObject.valueObservable.map { possibleValue -> String in
if let value = possibleValue {
return "Selected value is: \(value)"
} else {
return "No value selected"
}
}.bind(to: self.textLabel.rx.text).disposed(by: disposeBag)
}
1. バインディングはなぜ重要ですか?
上記のコードのように、textLabel.text
多くの場所に設定されている値と比較して、バインディングが確立された後、これはtextLabel
最後に 1 回だけ参照されます。応答性プログラミングを使用すると、宛先 (つまり、データのサブスクライバー) から開始して、元のデータの依存関係 (observable ()) に到達するまでデータ変形を追跡することができますobservable
。こうすることで、データパイプライン可观察量
と3つが分離されます数据变形
。订阅者
データ変換の部分は、リアクティブ プログラミングがもたらす最大の利点ですが、学習曲線が最も急な部分でもあります。
2. RxSwift のいくつかの基本的な型
Observable
UI 要素を変換、サブスクライブ、またはバインドできるオブザーバブルです。PublishSubject
これはObservable
一種の であり、それを通じて値を送信でき、これらの値はオブザーバーに送信され、最終的にサブスクライバーはコールバックを受け取ります。BehaviorSubject
,に似ていReplaySubject
ますPublishSubject
が、オブザーバーが接続されていないときに値を送信できます。新しいオブザーバーが存在する場合、「リプレイ」バッファーに一時的に保存されている以前に送信された値を受信します。Disposable
および は、DisposeBag
それぞれ 1 つ以上のサブスクリプションのライフサイクルを制御するために使用されます。がDisposable
破棄されるか手動で破棄されると、サブスクリプションの動作が終了し、サブスクリプションの監視可能なコンポーネントもすべて解放されます。
3. RxSwiftの部分変換機能
Map
:地図Filter
:フィルターconcat
: 2 つの Observable A と B は「シリアル化」されており、onComplete
A が送信する前に A のメッセージのみが受け入れられ、A が onComplete を送信した後に B のメッセージが受信されます。Merge
: 複数の監視可能なシーケンスをマージします。そのうちの 1 つがメッセージを発行すると、サブスクリプション コールバックを受け取ります。take
およびなどtake(while
:take(until
サブスクリプションの数を制御するか、トリガー条件に従ってサブスクライブします。flatMapLatest
:flatMapLatest
返された最新のサブスクリプションObservable
(flatMapLatest
関数によって返されたサブスクリプションObservable
) のみを保持します。
より具体的なコンテンツは、RxSwift Web サイトでご覧いただけます。
3. 双方向バインディングの例
ほとんどの場合、一方向バインドのみが必要ですが、場合によっては双方向バインドが必要になる場合があります。以下は双方向バインドの例です: ログイン ページの入力ボックスは、VM のデータに双方向バインドする必要があります。
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var label: UILabel!
var userVM = UserViewModel()
let disposeBag = DisposeBag()
override func viewDidLoad() {
//将用户名与textField做双向绑定
userVM.username.asObservable().bind(to: textField.rx.text).disposed(by: disposeBag)
textField.rx.text.orEmpty.bind(to: userVM.username).disposed(by: disposeBag)
//将用户信息绑定到label上
userVM.userinfo.bind(to: label.rx.text).disposed(by: disposeBag)
}
}
// 我们可以将双向绑定定义一个为一个操作符(官方demo中有这个文件,可拷贝)
// 上述中双向绑定的代码可以简化为:
//将用户名与textField做双向绑定
_ = self.textField.rx.textInput <-> self.userVM.username
興味があれば、定型プロジェクトが github.com/ReactiveX/R…にRxSwift
あります。github