Saturday, May 2, 2026
HomeiOS DevelopmentConstructing enter varieties for iOS apps

Constructing enter varieties for iOS apps

[ad_1]

Discover ways to construct complicated varieties with my up to date assortment view view-model framework with out the wrestle utilizing Swift.

iOS

This methodology is just not working, since cells within the kind are going to be reused and this results in some inconsistency… please learn my different put up. 🤷‍♂️

CollectionView and enter varieties

My CollectionView framework simply received a HUGE replace. There are many new modifications, however one of many greatest enchancment is the best way I cope with view fashions. Up to now, you had to make use of lengthy operate names in your view mannequin together with the generic view & mannequin class names. You probably have ever learn my final UICollectionView information you must know what I am speaking about. Excellent news: I’ve a manner higher resolution now! 😉

This replace not simply cleans up my code quite a bit, however it permits me so as to add customized view mannequin handlers, so I can work together with enter fields, toggles, and so on. in a ridiculously straightforward manner. One other enormous enchancment is that I began to make use of view identifiers. It was unintended discovery, I solely needed to search for another resolution for figuring out views by tags, then I had this good concept: why not lookup cells by ids as properly?

Because of this I am now in a position to create varieties by utilizing the framework. I nonetheless consider that assortment views are the final word constructing blocks for a lot of the functions. Yeah, you’ll be able to nonetheless say that there isn’t a silver bullet, however I am simply high-quality if this resolution can cowl 90% of the my use-cases. In spite of everything, a lot of the apps are simply visualizing JSON knowledge in a pleasant, or not-so-nice manner. 🤷‍♂️ #sarcasm


Reusable kind parts

Let’s construct a kind by utilizing the model new framework. Initially, you may must combine it by utilizing a bundle supervisor. I actually hope that in a number of weeks we will use Swift Bundle Supervisor, till than you you must go together with CocoaPods or carthage.


supply 'https://github.com/CoreKit/CocoaPods.git'
pod 'CollectionView', '~> 2.0.0'


github "CoreKit/CollectionView" "2.0.0"

Now let’s create a reusable cell for our enter fields. Be at liberty to make use of a xib file as traditional, the one distinction within the implementation goes to be that I take away the goal listener within the reset methodology. We’ll add one afterward within the view-model. 🎯

import Basis
import CollectionView

class InputCell: Cell {

    @IBOutlet weak var textField: UITextField!

    override func reset() {
        tremendous.reset()

        self.textField.removeTarget(nil, motion: nil, for: .editingChanged)
    }
}

I am additionally going to create a easy entity for displaying a placeholder if the shape area is empty and storing the precise worth of the enter area, let’s name this InputEntity.

import Basis

struct InputEntity {
    var placeholder: String
    var worth: String?
}

Now the toughest half: making a connection between the view and the mannequin.

import Basis
import CollectionView

class InputViewModel: ViewModel<InputCell, InputEntity> {

    var editingChangeHandler: ViewModelHandler?

    override var top: CGFloat {
        return 60
    }

    override func updateView() {
        self.view?.textField.placeholder = self.mannequin.placeholder
        self.view?.textField.textual content = self.mannequin.worth

        self.view?.textField.addTarget(self,
                                       motion: #selector(self.editingChanged(_:)),
                                       for: .editingChanged)
        self.view?.textField.addTarget(self,
                                       motion: #selector(self.editingDidEnd(_:)),
                                       for: .editingDidEnd)
    }

    func onEditingChange(_ handler: @escaping ViewModelHandler) -> Self {
        self.editingChangeHandler = handler
        return self
    }

    @objc func editingChanged(_ textField: UITextField) {
        self.mannequin.worth = textField.textual content
        self.editingChangeHandler?(self)
    }

    @objc func editingDidEnd(_ textField: UITextField) {
        print("nothing-to-do-here-now...")
    }
}

It is fairly a fancy view mannequin, however it will probably do quite a bit as properly. The very first thing that you must perceive is the ViewModelHandler which is principally a generic alias that you would be able to make the most of within the view fashions. It offers you the power to move across the type-safe view-model for the callbacks. You may see that afterward.

The second main change is the updateView methodology, which is used to replace the view primarily based on the information coming from the mannequin. I am additionally including my goal listeners to my view, so I can deal with consumer enter instantly contained in the view-model class.

The onEditingChange methodology is the “public” api of the view-model. I exploit the on prefix now for including handlers, and listeners to my view-models. It principally calls the saved block if a change occasion occurs. You’ll be able to add as many occasion handler blocks as you need. I actually hope that you’re going to get the grasp of this strategy.

Yet one more factor: returning the the peak of the cell is a one-liner now! 🎊


Composing varieties and extra

The plan is for now to have an enter kind with two enter fields. One for the e-mail deal with, the opposite goes for use for the password. The trick goes to be that this time I will not present you your entire code, however you must work out the remainder.

Nevertheless I will present you all the things that you’re going to ever must know with a view to make your individual varieties, even some complicated ones. Don’t be concerned, it is only a few strains of code.

import UIKit
import CollectionView

class ViewController: CollectionViewController {

    override func viewDidLoad() {
        tremendous.viewDidLoad()

        let grid = Grid(columns: 1, margin: UIEdgeInsets(all: 16), padding: .zero)
        self.collectionView.supply = .init(grid: grid, [
            [
                InputViewModel(id: "email-input", .init(placeholder: "Email", value: nil))
                .onEditingChange { viewModel in
                    guard let passwordViewModel = viewModel.by(id: "password-input") as? InputViewModel else {
                        return
                    }
                    passwordViewModel.model.value = viewModel.model.value ?? ""
                    passwordViewModel.updateView()
                },
                InputViewModel(id: "password-input", .init(placeholder: "Password", value: nil)),
            ],
        ])
        self.collectionView.reloadData()
    }
}

If you happen to’ve ever labored with my assortment view framework, you must know that I all the time use a grid system, as a result of I do not actually prefer to calculate numbers.

The supply is a set of view-models, grouped by sections. The one attention-grabbing half right here is that sources can now be initialized with an array of sections and view-models.

If you happen to initialize a view-model with and identifier, afterward you’ll be able to question that one by the id. That is precisely whats occurring contained in the modifying change handler block. Each view-model has the power to return another view-model by the id. View-models are type-safe by default, the viewModel handed contained in the block too, because of the generic ViewModelHandler alias.

So on this little instance, in case you sort one thing into the primary enter area, the very same textual content will seem within the second textual content area. You will get all of the view fashions by id while you want them. For instance if you must submit this manner, you’ll be able to seize the e-mail and password fields by utilizing the identical strategy.


Constructing a login kind

I problem you to construct a login kind by yourself by utilizing my framework. I assure yout that it should not take greater than 30mins of labor. I will present you the ultimate view controller that I might use, so this would possibly offers you some assist.

If you wish to boost issues somewhat bit, you’ll be able to even add a checkbox for accepting the privateness coverage. The primary concept right here is that you must create reusable parts for each single merchandise in your kind. So for instance a ToggleView with a corresponding view-model can be a superb strategy (additionally works for buttons). 🤫

Right here is the ultimate trace, you solely need to make your individual view-models and views…

import UIKit
import CollectionView

class ViewController: CollectionViewController {

    enum Ids: String {
        case e mail = "email-input"
        case password = "password-input"
        case privacyPolicy = "privacy-policy-checkbox"
        case submit = "submit-button"
    }

    override func viewDidLoad() {
        tremendous.viewDidLoad()

        let grid = Grid(columns: 1, margin: UIEdgeInsets(all: 16), padding: .zero)
        self.collectionView.supply = .init(grid: grid, [
            [
                InputViewModel(id: Ids.email.rawValue, .init(placeholder: "Email", value: nil))
                .onEditingEnd { viewModel in
                    guard let passwordViewModel = viewModel.by(id: Ids.password.rawValue) as? InputViewModel else {
                        return
                    }
                    passwordViewModel.view?.textField.becomeFirstResponder()
                },
                InputViewModel(id: Ids.password.rawValue, .init(placeholder: "Password", value: nil, secure: true))
                .onEditingEnd { viewModel in
                    viewModel.view?.textField.endEditing(true)
                },
            ],
            [
                ToggleViewModel(id: Ids.privacyPolicy.rawValue, .init(label: "Privacy policy", value: false))
                .onValueChange { viewModel in
                    guard let submitViewModel = viewModel.by(id: Ids.submit.rawValue) as? ButtonViewModel else {
                        return
                    }
                    var model = submitViewModel.model
                    model.enabled = viewModel.model.value
                    submitViewModel.model = model
                    submitViewModel.updateView()
                },
            ],
            [
                ButtonViewModel(id: Ids.submit.rawValue, .init(title: "Submit", enabled: false))
                .onSubmit { viewModel in
                    guard
                        let emailViewModel = viewModel.by(id: Ids.email.rawValue) as? InputViewModel,
                        let passwordViewModel = viewModel.by(id: Ids.password.rawValue) as? InputViewModel
                    else {
                        return
                    }
                    
                },
            ],
        ])
        self.collectionView.reloadData()
    }
}

That is it for now, an virtually full login kind, with only a few strains of code. After all there may be an underlying framework, however in case you verify the supply code, you may truly see that it incorporates nothing that will be thought-about as black magic. 💫

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments