2017-01-02 20 views
1

私はModel-View-ControllerデザインパターンをCocoaアプリケーション(Swiftで書かれています)に適用したいと思います。有名人の例を想定してみましょう:アプリケーションはテキストフィールドと追加ボタンを表示する必要があります。人物の名前をテキストフィールドに入力し、追加ボタンをクリックすることで配列に格納することができます(配列の内容はテーブルビューで表示されます)。ここで、ストーリーボードにはすべてのビュー関連のものが含まれ、Personクラス(変数名付き)はModelクラスを構成します。ビューコントローラは、データの表示(たとえば、テーブルビューのデリゲートとデータソース)を受け取り、その名前を抽出してどこかに配置するIBActionを持っています。しかし、私は実際にどこの名前を保持する配列を配置するか分からない。ビューコントローラーでもそれを使用できますか(これは最も簡単な解決策です)。それとも別の場所?もし、アプリケーションが異なるビュー(異なるビューコントローラを持つ)に複数のデータ保持構造を持つようになると、ますます複雑になるでしょうか? UITableViewControllerまたはのUIViewControllerからMVC:データを保存する場所は?

+0

実際のプロジェクトでは、この配列をデータベース、ローカルまたはリモートデータベースに保存する必要があります。この場合、モデルの保存またはデータベースからの取得を担当するサービスを持つことができます。どのViewControllerもそのServiceClassを使用します。 –

+0

私が正しく理解していれば、あなたは@bubuxuの答えを説明しますが、いくつかの保存/書き込み機能(ディスクまたはデータベースのいずれか)を使用して説明します。つまり、一部のビューコントローラがアクセスする必要があるときはいつでも、データをロード/保存する必要があります。処理に多くのデータがある場合は特に計算コストがかかりませんか? – DaPhil

答えて

0

1)のViewController():必要ならば入力セル又は個人の細胞を含む:

class ViewController: UITableViewController, UITextFieldDelegate { 

    var model = ViewModel() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     tableView.register(UITableViewCell.self, forCellReuseIdentifier: "personCell") 
     let nib = UINib(nibName: "InputTableViewCell", bundle: nil) 
     tableView.register(nib, forCellReuseIdentifier: "inputCell") 

     // Request or load the data into model 
     // requestData() & tableView.reloadData() here 

    } 

    // MARK: - UITableViewDataSource 

    override func numberOfSections(in tableView: UITableView) -> Int { 
     return 2 
    } 


    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return section == 0 ? 1 : model.persons?.count ?? 0 
    } 


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     if indexPath.section == 0 { 
      let cell = tableView.dequeueReusableCell(withIdentifier: "inputCell", for: indexPath) 
      if let inputCell = cell as? InputTableViewCell { 
       inputCell.textField.text = model.input 
       inputCell.textField.delegate = self 
       inputCell.textField.addTarget(self, action: #selector(textFieldEditing(_:)), for: .editingChanged) 
       inputCell.buttonAdd.addTarget(self, action: #selector(buttonAddTapped(_:)), for: .touchUpInside) 
      } 
      return cell 
     } else { 
      let cell = tableView.dequeueReusableCell(withIdentifier: "personCell", for: indexPath) 
      let person = model.persons?[indexPath.row] 
      cell.textLabel?.text = person?.name 
      return cell 
     } 
    } 

    // MARK: - Event Handler 

    func textFieldEditing(_ sender: UITextField) { 
     model.input = sender.text 
    } 

    func buttonAddTapped(_ sender: UIButton) { 
     if let name = model.input, name.characters.count > 0 { 
      let person = Person() 
      person.name = name 
      model.addPerson(person) 
      model.input = nil 
      // Also save data to CoreData if you want to retrieve them again later 
      // saveData() 
     } 
     tableView.reloadData() 
    } 


} 

2)セルを定義します。新しいクラスを作成するときは、「XIBファイルも作成する」もチェックして接続し、UIを作成します。モデルの定義)

class ViewModel { 

    var persons: [Person]? 
    var input: String? 

    func addPerson(_ person: Person) { 
     if persons == nil { persons = [] } 
     persons?.append(person) 
    } 

} 

4:

class InputTableViewCell: UITableViewCell { 

    @IBOutlet weak var textField: UITextField! 
    @IBOutlet weak var buttonAdd: UIButton! 

} 

3)ビューモデルを定義

class Person { 
    var name: String? 
} 
+0

基本的に言えば、配列を保持し、アクセサーメソッドを提供する追加のクラスがあります。しかし、ViewModelの特定のインスタンスにデータを追加するだけなので、データにアクセスするのが好きな複数のビューを作成したら、これは好ましくありませんか? – DaPhil

+0

MVC(またはMVVM)パターンのクラスのセットを持っています:モデル - ViewModel - View - Controller、私のサンプルを見ると、モデル、ビューモデル、ビュー、コントローラクラスがあります。 – bubuxu

0

モデル:

あなたはデータベースをしたい、またはコアデータになります。

ITのいくつかのコーナーでは、mySQLデータベースまたはXMLファイルの後ろに「モデル」があると考えられているので、CDを分けています。ディスカッションのために何かを開いているように、CDには長所と短所があります。多くの人々は、実装後に物事を拡大する最大の弱点の1つを考えています。

異なるビュー(異なるビューコントローラ)で複数のデータを保持する構造でアプリケーションがますます複雑になる場合はどうなりますか?

これは私にとってはモデルにとって重要なことです。これは単純なSQL(またはリレーショナル)データベースを意味します。私がリレーショナルで何を意味するのかわからない場合は、それを見て、数日間それを勉強してください。 (ヒント:あなたがすでに "人格クラス"と話しているときにあなたはすでにそこにいます。あなたのクラス(名前、タイプ、プロパティ)に合わせて、あなたのクラスをデータベーステーブルに合わせてください。

しかし、スケーラビリティとティア(モデル、ビュー、コントローラ)を心に留めておいてください。スウィフトはプロパティを計算しました。「ヨーロッパに住んでいる人の数」などのクエリを実行する場合は、データをパイプクリーナー上に残して、より良いパフォーマンスを発揮しますが、「John Doeの誕生日までの日数」のようなものを表示したい場合は、コントローラー側の計算されたプロパティーまたは呼び出し可能な関数

あなたはまた、ローカルまたはクラウドを決定したいと思います。Facebookには明らかにデータベースがありますそれは雲の中にある。しかし、私のサードパーティのポッドキャストアプリ(曇りのないBTW)には、ある種のローカルデータベースがあります。

ビュー:

あなたはこの上の良いハンドルを持っているように見えます。 Xcodeは、ほとんどの場合、MVCに頼っています。 Interface Builderで完全に固執することができれば、あなたはすでにこれを持っています。

しかし、(私のような)一部のコーダーはそれを行うことができません。すべてのAppleが自動レイアウトの制約でうまくやっているので、iPad上のすべての向き(分割画面やスライドアウトが使用されていない場合を含む)が現在の通常のサイズと同じように、私のアプリケーションは、私のGLKViewの画面スペースを最大にするために、UISliderコントロールを下(縦)から右(横)に移動する必要があります。これは、少なくともいくつかのものをコーディングすることを意味します(オリエンテーションの変更とスーパービューの境界)。 IBは設計時にコードを処理できないため、すべてのサブビューをコードに移動してIBを削除することに決めました。私はIBを使うことができるXcode 8を期待していました。新しいIBの両方のもので遊んだ後も、それはまだ価値がないことに気が付きました - スーパービューの境界に基づいてアクティブ/非アクティブにするための制約配列が必要です。

短いストーリー:IBはうまく機能し、可能な限り使用してください。しかし、制限があることを覚えておき、必要に応じてビューレイヤのコードに入るのを恐れないでください。

コントローラー:

まず第一に、残ってすべては「コントローラ」で、あなたは「モデル」との事から、「ビュー」を削除した後ことに注意してください。

もちろんです。もちろん!ビューコントローラはビ​​ュー(およびサブビュー)にデータを表示する必要があります。また、ボタン押下スライダの変更など、ユーザからのアクションを処理する必要があります。しかし、データベースのデータを取得するのはどうですか?サードパーティのWebサービスから価格や税務情報を取得するのはどうでしょうか?またはあなたのために、UITableViewの人々(連絡先?)のリストを表示するのはどうですか?

あなたのすべてをあなたのビューコントローラに入れたら、おめでとうございます! UIViewController "cruft"について学習しました。私たちはこれをすべてやってきました.Xcode MVCのやり方を学ぶことのすべてです。それは科学の何か、そして何がうまくいくかを知る何かのアートです。 (それは主に経験ですが)

あなたのアプリが成長するにつれ、より多くのUIViewControllerがあるはずです。 Person、Countryなどのような他のクラスもあるでしょう。最終的に、さまざまなクラスの拡張を作成し、クラスのプロトコルを作成します。今すぐ、簡単な質問:これらのものをどのように整理しておきますか?別々のファイル、グループ、何?あなたは、フレームワークターゲットが最も効果的であることが分かります。

"コントローラ"組織をコーディングする前に、あなたの "モデル"を釘付けするよりも、もっと重要なことかもしれません。

関連する問題