2

リファクタリングしたい現在のコードベースがあります。コントローラー (または iOS に慣れている人にとってはビューコントローラー) は約 2000 行あり、多くのことを行っています。

コントローラーは次のことを担当します。
1) ビューとモデル間の通信

1.1) ビューからのコールバック/アクションの処理
1.2) ジェスチャーの処理。
1.3) モデルからビューへのデータの受け渡し。

2) モデルが空の場合、Web リクエストを作成します。

2.1) URL の準備と接続ハンドラへのリクエストの送信。
2.2) 解析ロジック

3) UIのカスタマイズ

3.1) UI のマイナーな変更。

4) ビジネスロジック。

4.1) いくつかのレポートの計算のビジネス ロジックを扱うコードが少しあります。

モデルとビューにいくつかの責任を委任することを考えていました。それをどうやって進めるかについて何か考えはありますか?

また、より具体的には、誰が Web リクエスト モデルまたはコントローラーを作成する責任があるのか​​知りたいですか?

4

2 に答える 2

2

簡単に保守できるコードを書くのに役立つ概念がいくつかあります。

  1. 具体的なモデル オブジェクト (たとえば、サービスから天気情報を要求する場合Weather、特定の天気予報を表すクラス ( a city、 a temperature、およびnarrativeプロパティなど) がある場合があります) に加えて、データ コントローラー オブジェクトも使用します。必要に応じて、キャッシュ、永続ストレージ、または Web からのオブジェクトの要求 (多くの場合、この順序で)。レスポンシブ UI を設計する場合、キャッシュなどは非常に重要になる可能性があるため、Web サービスの単純な要求のみに依存することには注意が必要です。

    私にとって重要なポイントは、ビューまたはビュー コントローラーのいずれかがこのレベルの詳細をいじりたくないということです (ただし、些細な状況では、コントローラーから直接要求を行ったことがあることを告白します)。理想的には、ビュー コントローラーがデータ コントローラーの非同期要求を開始し、(a) 取得するモデル オブジェクトのパラメーターを含む完了ブロックを渡します。(b) a NSError.

    これがどのように見えるかの例を以下に示します。

  2. 上記から推測できるように、私はしばしば、Web リクエストの開始とレスポンスの独自のオブジェクトへの解析の詳細も抽象化します (データ コントローラーは十分に複雑で、キャッシュや永続的なストレージなどを管理する可能性があるため)。 . 私は通常NSOperation、リクエスト/解析タスクにサブクラスを使用します (これは、完了ブロックを使用した非同期リクエストに適しています。UI が別のものに移動した場合に保留中のリクエストをキャンセルする機能など)。したがって、私のデータ コントローラーは、キャッシュされたストレージや永続的なストレージが要求を満たすことができないと判断した場合、非同期の要求/解析操作を開始します。

  3. ビューコントローラーに割り当てた他のいくつかの責任をリストしますが、抽象化するのが最善の場合もあります。

    • 1.2) ジェスチャの処理 - ジェスチャが少し複雑になる場合 (水平方向のみ、端からスワイプなど)、実際にジェスチャ ハンドラをサブクラス化し、View Controller とジェスチャ ハンドラとのやり取りを大幅に簡素化します。

    • 3) UI のカスタマイズ - UI に多くのカスタマイズが必要な場合は、適切なビューもサブクラス化することがよくあります。特に と を使用するUITableViewCellUICollectionViewCell、View Controller コードを大幅に簡素化できます。また、マテリアルのカスタマイズが必要なビューは、多くの場合、ビュー自体のサブクラスでより適切に実行できます。


サンプル データ コントローラーの抽象化

したがって、次のように定義された完了ブロックがある場合があります。

typedef void(^WeatherRequestCompletion)(WeatherReport *weatherReport, NSError *error);

そして、次のようなインターフェイスを備えたデータコントローラーにメソッドがある場合があります。

- (WeatherRequest *)requestWeatherWithIdentifier:(CityIdentifier)cityIdentifier completion:(WeatherRequestCompletion)completion;

そして、私のView Controllerはそれを次のように使用します:

typeof(self) __weak weakSelf = self;

self.weatherRequest = [[WeatherModel sharedController] requestWeatherWithIdentifier:self.cityIdentifier completion:^(WeatherReport *weatherReport, NSError *error) {
    if (error) {
        // handle error
    }
    if (weatherReport) {
        weakSelf.cityLabel.text       = weatherReport.city;
        weakSelf.tempLabel.text       = [weatherReport.temperature stringValue];
        weakSelf.narrativeLabel.text  = weatherReport.narrative;
    }
}];

View Controller は、リクエストがどのようにフォーマットされているか、またはレスポンスがどのように解析されているかについて心配する必要はありません (これは、私のネットワーク リクエストNSOperationサブクラスの仕事です)。また、View Controller がキャッシングおよび/または永続ストレージ ロジックに関与しすぎてもいけません (それは私のデータ コントローラーの仕事です)。したがって、View Controller は、非常に論理的で理解しやすいものに蒸留する必要があります。

私のデータコントローラーがリクエストオブジェクトを返していることに注意してください(私にとっては、これは多くの場合、 a への単なる typedefNSOperationです)。ビュー コントローラーにこれへの参照を維持さweakせて、必要に応じてリクエストを簡単にキャンセルできるようにしdeallocます。

- (void)dealloc
{
    [_weatherRequest cancel];
}
于 2013-08-14T19:44:46.210 に答える
1

そのほとんどは、典型的な ViewController の動作のようです。Apple には、MVC アーキテクチャを詳細に説明した優れたドキュメントがあります: http://developer.apple.com/library/ios/documentation/general/conceptual/devpedia-cocoacore/MVC.html

「モデル オブジェクトが変更されると (たとえば、ネットワーク接続を介して新しいデータが受信される)、適切なビュー オブジェクトを更新するコントローラー オブジェクトに通知されます。」

これは、モデルがネットワーク アクティビティと更新を処理するのに適していることを示しています。他に変更できる唯一のことは、できるだけ多くの UI 作業をビューに配置することです。

于 2013-08-14T19:05:24.610 に答える