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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With