Table of contents

Problem statement

각각의 다른 구조를 가진 모델들을 하나의 재활용되는 화면에서 사용하려는 경우 타입 에러가 발생한다

Goals

하나의 재활용되는 화면에서 구조가 다른 모델들의 데이터를 보여주는 방법을 찾을 것이다

Proposed solution

다음과 같은 두 모델이 존재하고 화면 A와 B의 레이아웃이 동일하다고 가정한다

화면 A에서는 Employee의 이름과 나이를 보여주고 화면 B에서는 Employee 수, Company의 이름, 그리고 CEO 이름을 보여주려고 한다


struct Employee {
    let name: String
    let age: Int
}

struct Company {
    let name: String
    let ceo: String
    let employee: [Employee]
}

일반적으로 Company의 데이터를 가지고 화면을 만든다면 이런 방법이 될 것이다

struct CardView: View {
    let data: Company // Comapny type only
    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(data.name)
                .font(.headline)
            HStack {
                Label("\\(data.employee.count)", systemImage: "person.3")
                Spacer()
                Label("\\(data.ceo)", systemImage: "laurel.leading")
            }
            .font(.caption)
        }
        .padding()
    }
}

하지만 Employee 타입의 데이터는 사용할 수 없게 된다

그래서 먼저 각각의 모델에 extension을 만들어 데이터에 접근할 수 있도록 한다

extension Employee {
    var getName: String {
        return name
    }
    var getAge: Int {
        return age
    }
}

extension Company {
    var getName: String {
        return name
    }
    var getCEO: String {
        return ceo
    }
    var getEmployeeCount: Int {
        return employee.count
    }
}

예를 들어 Employee에서 getName은 직원의 이름을 Company에서 getName은 회사의 이름을 가져오는 것이다

그래도 여전히 데이터 타입 문제는 해결되지 않는다

이때 우리가 사용할 수 있는 방법은 바로 Protocol 이다

protocol CardViewData {
    var getName: String { get }
    var getAge: Int? { get }
    var getCEO: String? { get }
    var getEmployeeCount: Int? { get }
}

모델이 Protocol을 따르게 하면 두 데이터 구조가 달라도 데이터에 접근이 가능하기 때문에 하나의 화면에서 사용될 수 있다