Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting values out of view model structs

Tags:

ios

swift

I'm pretty new to swift. Currently, I'm attempting to create a view screen programmatically in Swift 4. The screen is supposed to have a number of images and textlabels. I created a view model with a struct of several declared images and strings.

The struct setup thats in my view model:

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)
    }
}

Question: How can I create an instance of ShareUIModel in a view controller and access the values?

like image 985
Dyson Dunkl Avatar asked Nov 13 '17 22:11

Dyson Dunkl


1 Answers

Generally, you can apply a MVM object to it's view in many ways. Personnaly, I recommend either a convenience initializer, or a custom variable with what's called a didSet value observer. Didset observers are called when their parameters are applied, without modifying the stored value.

So given a uivew subclass that can handle your model :

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
    }

}

So from here, you can either apply it onto your UIViewController's view by initializing it:

class Controller : UIViewController {


    override func viewDidLoad() {
        super.viewDidLoad()

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

}

This method means you have to set the size afterwards.

Or, you can build out the ShareView first, then apply the model object afterwards (say, from a user's selection, or from a network task) by applying the model onto ShareView's model parameter. This requires you to have a strong reference to it however, as in initializing it into your Controller class:

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.
    }

}

From this you should have ample examples to get creative with how to update a MVVM view with it's model object content. You would then also create methods to clear the content, dismiss it etc, depending on the use-case of the view itself.

like image 155
jlmurph Avatar answered Sep 24 '22 21:09

jlmurph