iOSにおけるMVVMアーキテクチャ設計の実践

iOS 開発では、MVC アーキテクチャ モードではコントローラーが肥大化しすぎるため、現在は MVVM アーキテクチャ モードの方が一般的です。以下に、iOS での MVVM の実践について簡単に紹介します。

1.iOS MVVM

次の図は、コントローラーではなく、ディスプレイまたはシャットダウン コントローラー(コーディネーター)として参照されるMVVM-Cデザイン モードの構造図です。実際の開発では、でタスクを完了することが一般的であるため、ここではコーディネーターには注意を払いません。CCoordinateController展示或者关闭控制器MVVM-C.png

1. 役割分担

比較するとMVC、新しいモジュールが追加されておりVM、各モジュールの役割は次のとおりです。

VM :との間のブリッジVMであり、表示に一連のプロパティを提供します。プロパティには、変形を変換するときに表示に変換する必要がある値が含まれています。iOS では、通常、ネットワーク要求と更新も担当しますVMViewModelViewModel

VC :VMメディアの属性間のViewバインディング関係を確立する責任を負い、インタラクション イベント応答の特定のロジックを担当します。グラフ内のコーディネーターが確立されていない場合は、通常、ページのジャンプ ロジックが含まれます。

V : ビューの具体的な作成とユーザー インタラクションの監視、モデル内のデータのプレゼンテーション ロジック。

M : アプリケーションに必要なデータの保存と管理、および関連するビジネス ロジックの実行を担当します。VまたはVM控制器組み合わせてはいけません。

RxSwift2.バインディングのためのリアクティブプログラミング

  • 上記は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 のいくつかの基本的な型

  • ObservableUI 要素を変換、サブスクライブ、またはバインドできるオブザーバブルです。
  • PublishSubject これはObservable一種の であり、それを通じて値を送信でき、これらの値はオブザーバーに送信され、最終的にサブスクライバーはコールバックを受け取ります。
  • BehaviorSubject,に似ていReplaySubject ますPublishSubjectが、オブザーバーが接続されていないときに値を送信できます。新しいオブザーバーが存在する場合、「リプレイ」バッファーに一時的に保存されている以前に送信された値を受信します。
  • Disposable および は、DisposeBagそれぞれ 1 つ以上のサブスクリプションのライフサイクルを制御するために使用されます。Disposable破棄されるか手動で破棄されると、サブスクリプションの動作が終了し、サブスクリプションの監視可能なコンポーネントもすべて解放されます。

3. RxSwiftの部分変換機能

  • Map:地図
  • Filter:フィルター
  • concat: 2 つの Observable A と B は「シリアル化」されており、onCompleteA が送信する前に 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

おすすめ

転載: juejin.im/post/7247566462088101948