Registration View Model
Tinder Firestore Swipe and Match
One little extra feature I'd like to include in this section is the ability to enabled/disable our register button depending on the inputs of our form. We'll first go over how this implemented in standard controller code so that its easy to understand. Lastly, I'll transform the code into a View Model using some Reactive Programming again. A lot of fun and many things to learn today.

Comments (9)
azhar
4 years ago
Mapping it out on a whiteboard helped to see how all the parts of mvvm and reactive code connect. I suggest mapping it out, helped a lot. Side note, @brian you and I have the same uniqlo grey camo sweatshirt jacket. It's amusing especially when i'm doing this course and both of us are wearing the same jacket lol
arian
4 years ago
Hi Brian, on using ternary operator : isFormValid == true ? (self.registerButton.backgroundColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1) , self.registerButton.setTitleColor(.white, for: .normal)) : (self.registerButton.backgroundColor = .lightGray,self.registerButton.setTitleColor(.gray, for: .normal)) i'm getting Expression of type '((), Void)' is unused, how can i silent this swift warning ?
Brian Voong
4 years ago
arian
4 years ago
this is the function in which i used ternary operator: fileprivate func setupRegistrationViewModelObserver() { registrationViewModel.isFormValidObserver = {[unowned self](isFormValid) in print("Form is changing, is it valid?",isFormValid) self.registerButton.isEnabled = isFormValid isFormValid == true ? (self.registerButton.backgroundColor = .green , self.registerButton.setTitleColor(.white, for: .normal)) : (self.registerButton.backgroundColor = .lightGray,self.registerButton.setTitleColor(.gray, for: .normal)) } }
Brian Voong
4 years ago
Igor Tkach
4 years ago
Read documentation backgroundColor -> UIColor? which optional. Swift complain about that and in second setTitleColor(_:UIColor?,for:) exactly the same optional in first parameter! Use Brian solution and avoid reading complexity!
Cinquain
4 years ago
Interesting techniques in this video, I'll have to watch it twice in order to grasp it fully. Fire nonetheless!
Cinquain
4 years ago
Third Time watching this video, I finally got it. Fire!
0zgur
4 years ago
Thank you Brian
Daniel Peach
4 years ago
Quick question on something I have been wondering for a while... When you create the handler functions (handleTextChange) how do you know it will automatically pass along a UITextField? I would guess it has something to do with the fact that a UITextField called it, but I can't find anything concrete in the docs. Is it safe to assume anything you add a target to will pass itself as an argument to the action handler? And, if so, is that because we set the target to self? Could we set the target to something else if we wanted?
Brian Voong
4 years ago
Eduardo Davila Nadal
4 years ago
Hello Brian, There are many complains about the layout constraints in the app in this point, things like: 2019-03-01 01:04:46.975350-0500 SwipeLover[8659:869866] [LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( .... Will attempt to recover by breaking constraint <NSLayoutConstraint:0x6000038d5d10 UIButton:0x7f93f481fbb0'Regístrame'.height == 50 (active)> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful. ... and so on... I know it doesn't break the app... but having that can be considered "good practice"? Thanks for this great course!
Eduardo Davila Nadal
4 years ago
I found you fixed in the "Download project" using lazy var selectPhotoButtonWidthAnchor = selectPhotoButton.widthAnchor.constraint(equalToConstant: 275) lazy var selectPhotoButtonHeightAnchor = selectPhotoButton.heightAnchor.constraint(equalToConstant: 275) and changing the values on override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { ... Only when in landscape is still complaining but you probably fix it if you decide to implement the keyboard solution Thank you Brian!!... I hope you get the time to prepare the UBER course!!
Subhodip
4 years ago
I believe the issue still exists for selectPhotoButtonWidthAnchor. PFC.. ( "<NSLayoutConstraint:0x600002cf86e0 H:|-(50)-[UIStackView:0x7f9fee4168f0] (active, names: '|':UIView:0x7f9fee415f10 )>", "<NSLayoutConstraint:0x600002cf88c0 UIStackView:0x7f9fee4168f0.trailing == UIView:0x7f9fee415f10.trailing - 50 (active)>", "<NSLayoutConstraint:0x600002cf7660 UIButton:0x7f9fee408830'Select Photo'.width == 275 (active)>", "<NSLayoutConstraint:0x600002cfd9a0 'UISV-canvas-connection' UIStackView:0x7f9fee4168f0.leading == UIButton:0x7f9fee408830'Select Photo'.leading (active)>", "<NSLayoutConstraint:0x600002cfda40 'UISV-canvas-connection' H:[UIButton:0x7f9fee408830'Select Photo']-(0)-| (active, names: '|':UIStackView:0x7f9fee4168f0 )>", "<NSLayoutConstraint:0x600002cf6c10 'UIView-Encapsulated-Layout-Width' UIView:0x7f9fee415f10.width == 896 (active)>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x600002cf7660 UIButton:0x7f9fee408830'Select Photo'.width == 275 (active)>
RobinHe0212
4 years ago
My solution is , for the registration button, add a height NSlayoutContraint, and make sure in the traitCollectionDidChange, let the isActive equals to false when the verticalSizeClass is compact, also for the overallStackView, the distribution will be fillequally and fill respectively for compact and regular status. Hope it works.
Omran_K
3 years ago
This error occurs when because the height constraint is added to the button before it has a superview. I don't really understand why but when I move the height constraint after the button has been added as a subview of the stack view, the error is gone. I tried to set the selectPhotoButton using a lazy var first but the issue persisted until I changed it to this: overAllStackView.addArrangedSubview(selectPhotoButton) selectPhotoButton.anchorSize(size: .init(width: 0, height: 300)) Would really like to understand why this is if anyone has an explanation. I like having whatever I can in the component initialization closure so this is kind of a bummer but it fixed the issue.
FranckNdame
4 years ago
Hi Brian, In my function, I am using anonymous variables: fileprivate func setupRegistrationViewModelObserver() { registrationViewModel.isFormValidObserver = { self.registerButton.isEnabled = $0 self.registerButton.backgroundColor = $0 ? colorA : colorB } } As you can see, I didn't use unowned or weak. Do you think it will create a retain cycle?
Omran_K
3 years ago
I think this will still create a retain cycle because self is used in the body when defining the observer: self.registerButton.isEnabled = $0 self.registerButton.backgroundColor = $0 ? colorA : colorB For the observer to know what these 2 lines mean, it will hold a reference to self.
omryno1
4 years ago
hey, I'm getting a weird warning : " [AutoFill] Cannot show Automatic Strong Passwords for app bundleID: com.od.TinderAppLBTA due to error: iCloud Keychain is disabled" since the password text field is set to : isSecureTextEntry = true the os tries to generate a strong password but I do not get the the strong password popup screen, what happens is the password text field gets coloured yellow and I cannot edit it or go back to the normal UITextField. and idea what should I do ?
omryno1
4 years ago
https://www.photobox.co.uk/my/photo/full?photo_id=501896985658
Brian Voong
4 years ago
HELP & SUPPORT