2017-11-13 12 views
5

私は非常に迅速です。現在、Swift 4でプログラムでビュー画面を作成しようとしています。画面には多数の画像とテキストラベルがあるはずです。私はいくつかの宣言されたイメージと文字列の構造体を持つビューモデルを作成しました。私の見解モデルのビューモデルの構造体から値を取得する

構造体のセットアップのthats:

import Foundation 
import UIKit 

struct ShareUIModel { 

    let heroImage: UIImage 
    let secondHeroImage: UIImage 
    let longHeroText: String 
    let shortHeroText: String 

} 

extension ShareUIModel { 

    static func testObject() -> ShareUIModel { 
     let heroImageImage = placeholderImage 
     let secondHeroImageImage = placeholderImage 
     let longHeroTextText = "long words" 
     let shortHeroTextText = "short words" 
     return ShareUIModel(heroImage: heroImageImage, secondHeroImageImage: secondHeroImage, longHeroText: longHeroTextText, shortHeroText: shortHeroTextText) 
    } 
} 

質問:どのように私は値をビューコントローラにShareUIModelのインスタンスを作成し、アクセスすることができますか?

+0

まあ、 'ShareUIModel'を解釈するように設計されたUIViewサブクラスが必要です。あなたは1つを作ったのですか?その場合は、コードを更新してください。さもなければ、私はこれに一般的なアプローチを掲示します。 – murphguy

+1

@murphyguy私はそれを解釈するためにUIViewを持っていない、私はビューコントローラで持っているほとんどがコンテナです。 –

答えて

5

一般に、MVMオブジェクトをさまざまな方法でビューに適用できます。個人的には、convenienceイニシャライザ、またはdidSet値オブザーバと呼ばれるカスタム変数のいずれかをお勧めします。受託者オブザーバーは、パラメーターが適用されたときに、保管された値を変更せずに呼び出されます。

だからあなたのモデルを扱うことができるuivewサブクラス与えられた:ここからそう

class ShareUIView : UIView { 


    var model : ShareUIModel? { 
     didSet { 
      guard let mode = model else { return } 
      applyModel(mode) 
     } 
    } 

    let heroImage = UIImageView() 
    let secondHeroImage = UIImageView() 
    let longHeroLabel = UILabel() 
    let shortHeroLabel = UILabel() 

    //Initializer 
    convenience init(model: ShareUIModel) { 
     self.init() 
     self.addSubview(heroImage) 
     self.addSubview(secondHeroImage) 
     self.addSubview(longHeroLabel) 
     self.addSubview(shortHeroLabel) 
     self.model = model 
    } 

    private func applyModel(_ model: ShareUIModel) { 
     self.heroImage.image = model.heroImage 
     self.secondHeroImage.image = model.heroImage 
     self.longHeroLabel.text = model.longHeroText 
     self.shortHeroLabel.text = model.shortHeroText 
    } 

    override func draw(_ rect: CGRect) { 
     super.draw(rect) 
     buildYourComponents() 
    } 

    func buildYourComponents() { 
     //This will be called whenever ShareUIView's size or layout is applied. 
     //code to build out your labels and imageViews 
    } 

} 

を、あなたはそれを初期化することによって、あなたのUIViewControllerviewにそれを適用することができ、次のいずれか

class Controller : UIViewController { 


    override func viewDidLoad() { 
     super.viewDidLoad() 

     let shareview = ShareUIView(model: ShareUIModel.testObject()) 
     view.addSubview(shareview) 
     shareview.frame = //whatever you want here.. 
    } 

} 

この方法後でサイズを設定する必要があることを意味します。

または、モデルをShareViewのモデルパラメータに適用することで、最初にShareViewを構築してから、後でモデルオブジェクトを適用することができます(たとえば、ユーザーの選択やネットワークタスクから)。これはあなたのコントローラクラスにそれを初期化のように、しかし、それへの強い参照を持っている必要があります。このことから

class Controller : UIViewController { 

    var shareView : ShareUIView = { //Initialized as a parameter of Controller instead 
     var v = ShareUIView() 
     return v 
    }() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     view.addSubview(shareView) //You add the view 
     shareView.frame = .zero//you build the view - .zero is just an example here. 
    } 

    func applyTheModelFromWherever() { 
     shareView.model = ShareUIModel.testObject() //you apply the model object. 
    } 

} 

あなたはそれがモデルのオブジェクトの内容とMVVMのビューを更新する方法で創造的な取得するために十分な例を持っている必要があります。また、ビュー自体のユースケースに応じて、コンテンツをクリアするメソッドや、それを閉じるメソッドなども作成します。

+0

人の経験則として、実際にモデルをUIViewサブクラスに格納していることを確認してください。特にフォームや編集可能なコンテンツでは、変更を追跡したり、代理人などに変更をプッシュしたりすることが容易になります。 – murphguy

+2

応答をありがとう、それは私が予想していた以上のものでした。 –

関連する問題