Reusable View Layout using Protocol & MVVM

Ritesh Gupta
Oct 30, 2017 · 3 min read

Idea 💡

The reason I have titled it “Reusable View Layout..” rather than simply “Reusable View..” because I’m NOT referring to object level reusability of views here. Rather I’ll be discussing about how we can reuse a view layout with the help of a protocol & MVVM. In the process I’ll share how we can outline a view’s interface, basically different configuration states, with a protocol which will enable us to inject different view-models into a view. In other words, the idea here is to design data agnostic modelling of a view layout.

MVVM

Before we move further, let’s get few things straight about MVVM. It’s one of most confusing design patterns out there so just want to make sure we are on the same page. It’s a design pattern where we make a view dependent on an intermediate model object called view-model. This view-model, gets some data (doesn't matter from network or persistence layer) and apply some decorative methods which is finally consumed by a view. E.g. if we have a profile view class –– ProfileView, we can create it’s view-model ProfileViewModel to configure it and save it's state.

class ProfileView: UIView {

var nameLabel: UILabel!

func configure(with model: ProfileViewModel) {
nameLabel.text = model.nameTitle
}
}

struct ProfileViewModel {

var nameTitle: String { return "Profile Title" }
}

Binding

As we can see ProfileView gets coupled with ProfileViewModel for any kind of configuration which happens when you use MVVM. This works well if your view, in the entire lifetime, will only have one kind of view-model. Now let's say we want to reuse ProfileView class which should be capable of showing both an Owner profile & a Guest profile.

Enum

To support this, we can convert ProfileViewModel into an enum where owner & guest will be different cases.

enum ProfileViewModel {

case owner
case guest

var nameTitle: String {
switch self {
case .owner: return "Hi, Owner"
case .guest: return "Hi, Guest"
}
}
}

Protocol

To achieve that “something”, we can use a protocol. A view could have an interface which could be outlined using a protocol. This interface could have all the configurable states of it’s view. Finally we can have different view-models conforming to it. This approach makes the view totally oblivious of the kinds of view-models it could be expecting. E.g,

class ProfileView: UIView {

...

func configure(with interface: ProfileViewInterface) {
nameLabel.text = interface.nameTitle
}
}

protocol ProfileViewInterface {

var nameTitle: String { get }
}
class OwnerViewModel: ProfileViewInterface {

var nameTitle: String { return "Owner Title" }
}

class GuestViewModel: ProfileViewInterface {

var nameTitle: String { return "Guest Title" }
}

class AdminViewModel: ProfileViewInterface {

var nameTitle: String { return "Admin Title" }
}

let view = ProfileView()

let ownerModel = OwnerViewModel()
let guestModel = GuestViewModel()
let adminModel = AdminViewModel()
view.configure(...)// here we can pass any of the three above view-models since they all conform to ProfileViewInterface

Swift Sundae 🍨

Every sundae has a different flavour, so does best…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store