Intro MVVM Card View Models
Tinder Firestore Swipe and Match
In this lesson, I would like to introduce the concept of a View Model into our project. This purpose of this idea is to abstract the view presentation of what can possibly be drawn inside of a card. We'll first define a CardViewModel class that encapsulates the elements and layout of a card. Next, we'll utilize this view model layer and transform our users into view objects for our cards to consume. This approach will show you how you can utilize MVVM in your projects.

Comments (9)
Anas Belkhadir
4 years ago
Hello .I have see many time you whenever you make Struct Model you copy the constructor i can suggest to use Model.init , it's will help you with autocomplete . Thanks.
azhar
4 years ago
Thanks for this
Brian Voong
4 years ago
Kevin Jefferson
4 years ago
Hello Brian, loving the videos, i have a question on the app tik tok(musical.ly) they have set up up so that when you swipe the videos the homebuttonsbar stays in place but at the same time the video's can be kind of seen through the tabbar i do not know hoe much better to explain but how could i get that with the stackviews you have made?
Kevin Jefferson
4 years ago
https://www.google.nl/search?q=tik+tok.home+page&client=ms-android-samsung&prmd=vin&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiM7vnOhdbeAhVE6qQKHZE4B_YQ_AUoAnoECA0QAg&biw=360&bih=560#imgrc=b5UMBRiE1EOuVM like this image
Brian Voong
4 years ago
Christophe Bugnon
4 years ago
I don't really like to introduce UIKit in Model, many reasons: If I code with TDD and I want to create a MacOS framework for getting the fast test and don't have simulator run all times I run my test, I can't. Also because it will create a monolithic architecture, no probs for it at the start but as my application growth I'll rapidly get problems. What do you think about it? I prefer get something like that in my ViewModel: static func userToCardViewModel(user: User) -> CardViewModel { let attributedText = NSMutableAttributedString(string: user.name, attributes: [.font: UIFont.systemFont(ofSize: 32, weight: .heavy)]) attributedText.append(NSAttributedString(string: " \(user.age)", attributes: [.font: UIFont.systemFont(ofSize: 24, weight: .regular)])) attributedText.append(NSAttributedString(string: "\n\(user.profession)", attributes: [.font: UIFont.systemFont(ofSize: 20, weight: .regular)])) return CardViewModel(imageName: user.imageName, attributedString: attributedText, textAlignment: .left) } What do you think about it ? URL Diagram below: https://bit.ly/2LBXsWp
Brian Voong
4 years ago
Christophe Bugnon
4 years ago
Thanks for your fast reply. Ok good then, I never really use MVVM, but I like having a way out for dependency issues. It will fast become a nightmare if the application growth. By the way, excellent course again. I just miss one and I expect to quickly overcome this problem! : ) Big fan of your work!
Tube
4 years ago
I think adding UIKit to the Model is not a design tradeoff: it is a mistake, because it breaks the MVVM pattern.
Tokyojogo
4 years ago
Christophe, How did you create the cardViewModels array in the HomeController using this?
Brian Voong
4 years ago
FranckNdame
4 years ago
I am guessing he did something like this: let cardViewModels = [ CardViewModel.cardViewModel(fromUser: User(name: "Jane", age: 20, proffession: "Computer Science Student", imageName: "l1")), CardViewModel.cardViewModel(fromUser: User(name: "Xiomi", age: 23, proffession: "Data Scientist", imageName: "l2")) ]
FranckNdame
4 years ago
@Tokyojogo
majdjamaleddine@gmail.com
4 years ago
Hello Brian, First I would like to thank you for these well drafted codes. Secondly, I would like to ask you whether the below would match the concept of MVVM. Under CardViewModel, I included: static func userToCardViewModel(user: User) -> CardViewModel { let attributtesName: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 34, weight: .heavy) ] let attributesAge: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 24, weight: .regular) ] let attributesProfession: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 20, weight: .regular) ] let attributedText = NSMutableAttributedString(string: "") attributedText .append(NSAttributedString(string: user.name, attributes: attributtesName)) attributedText.append(NSAttributedString(string: " \(user.age)", attributes: attributesAge)) attributedText.append(NSAttributedString(string: "\n \(user.profession)", attributes: attributesProfession)) return CardViewModel(imageName: user.imageName, attributedString: attributedText, textAlignment: .left) } Under Home controller, I included: fileprivate func setupDummyCards() { users.forEach { (user) in let cardViewModel = CardViewModel.userToCardViewModel(user: user) let cardView = CardView(frame: .zero) cardView.cardViewModel = cardViewModel cardsDeckView.addSubview(cardView) cardView.fillSuperview() } } Thanks
Tokyojogo
4 years ago
Hi Brian, can you please check this page (video 7). Its too big so I can't play it. Its bigger than the screen...
Brian Voong
4 years ago
Tokyojogo
4 years ago
the video is showing but its like 3 times the width of the screen so the only way I can watch is if I click on full screen. I'm using firefox. Its weird because all the other pages are ok. just this one.
Brian Voong
4 years ago
Cinquain
4 years ago
wow, what a great video!
Cesar Bess
4 years ago
I see that using attributed strings solves the problem, but why not having another labels for that?
Cesar Bess
4 years ago
Also, why not setting all those properties from viewModel inside CardView? If you have a card with a lot of properties the code could get really messy.
Brian Voong
4 years ago
NessGrey
4 years ago
Hi Brian. I saw another variation of MVVM. In it, modelView catch all the users and have functions for returning calculated data to the view in viewController. View object was just with properties, viewController didn't catch Users data array, viewModel do everything (catch users and returning data for views). What you think, is it correct implementation of MVVM or its smth various?
Maurice Kraus
4 years ago
You are absolutely right, the original Microsoft approach (from which this architectural pattern is derived) differs greatly from this approach. But I guess why Brian isn't following this is because it would add extra complexity to the course, because you need some kind of reactive bindings (i.e. two-way bindings), which makes it hard for beginners to understand because the whole app already has its own level of complexity and people came for Tinder and not MVVM. If you want to know more about MVVM, I guess Ray Wenderlich has some good articles, and there are many on medium. I've read Advanced App Architectures for iOS (RW), which provides a pretty good tutorial for really complex applications, you should check it out. Basically, the original MVVM pattern is structured as follows: The ViewModel owns the model and other services and the controller retains the View and the ViewModel, every time the Model changes this triggers an action in the ViewModel. This informs the controller that the view needs to be changed.
NessGrey
4 years ago
Thanks, for an answer, I was little confused.I look at course Advanced App Architectures for iOS (RW) and thinking abut get it, may be will do
BobbyAxelrod
4 years ago
I found that if you save (CMD + S) the file that you created a struct/class in and then try to construct the object, you will get the autocomplete. You can tell when a file isn't saved when its kinda dark in the Project Navigator panel.
ndevereaux
4 years ago
Hey Brian, awesome course so far! Wondering if you'd have anything against adding a custom initializer to CardViewModel and pass in a User instead of adding a function on User to create a CardViewModel?
Brian Voong
4 years ago
HELP & SUPPORT