[SwiftUI] Generics

Junyoung Park·2022년 8월 21일
0

SwiftUI

목록 보기
36/136
post-thumbnail

How to use Generics in Swift | Advanced Learning #8

Generics

구현 목표

  • 제네릭은 구체적 타입을 추상적 타입으로 받도록 할 수 있는 방법
  • 제네릭 구현을 통해 함수, 타입의 확장성이 매우 증가(타입마다 구조체를 선언할 필요없이 하나의 보편, 추상화된 구조체 선언 충분)
  • 뷰 또한 제네릭 타입을 통해 다른 뷰의 이니셜라이저에 필요한 값으로 넘길 수 있음

구현 태스크

  1. 제네릭 타입의 구조체 구현
  2. 제네릭 타입을 통해 특정 뷰를 다른 뷰의 파라미터로 넘기기 ( 서브 뷰 활용)

핵심 코드

struct GenericModel<T> {
    let info: T?
    
    func removeInfo() -> GenericModel {
        GenericModel(info: nil)
    }
}

struct GenericView<T:View>: View {
    let content: T
    let title: String
    var body: some View {
        VStack {
            Text(title)
            content
        }
    }
}
  • 스위프트의 제네릭은 CustomType 등 별도의 용어로 사용해도 상관없지만, <T>가 일반적으로 사용됨
  • 스우프트의 타입 추론을 통해 구조체 이니셜라이저에서 사용되는 데이터 타입을 구조체 선언 시 넘겨줄 수 있다면 GenericModel<String>이 아니라 GenericModel을 통해 선언 가능.
  • View 또한 View 프로토콜을 준수하는 구조체라는 점에서 <T:View>를 통해 T가 뷰임을 제네릭으로 전달 가능, 서브 뷰로 활용한 뷰를 파라미터처럼 넘길 수 있음

소스 코드

import SwiftUI

struct StringModel {
    let info: String?
    
    func removeInfo() -> StringModel {
        StringModel(info: nil)
    }
}

struct BoolModel {
    let info: Bool?
    
    func removeInfo() -> BoolModel {
        BoolModel(info: nil)
    }
}

struct GenericModel<T> {
    let info: T?
    
    func removeInfo() -> GenericModel {
        GenericModel(info: nil)
    }
}

class GenericsViewModel: ObservableObject {
    @Published var stringModel = StringModel(info: "HELLO WORLD!")
    @Published var boolModel = BoolModel(info: true)
    @Published var genericStringModel = GenericModel(info: "Hello World!")
    @Published var genericBoolModel = GenericModel(info: true)

    func removeData() {
        stringModel = stringModel.removeInfo()
        boolModel = boolModel.removeInfo()
        genericStringModel = genericStringModel.removeInfo()
        genericBoolModel = genericBoolModel.removeInfo()
    }
}

struct GenericView<T:View>: View {
    let content: T
    let title: String
    var body: some View {
        VStack {
            Text(title)
            content
        }
    }
}

struct GenericsBootCamp: View {
    @StateObject private var viewModel = GenericsViewModel()
    var body: some View {
        VStack {
            GenericView(content: MatchedGeometryEffect(), title: "NEW VIEW!")
            Text(viewModel.stringModel.info ?? "NO DATA")
                .onTapGesture {
                    viewModel.removeData()
                }
            Text(viewModel.boolModel.info?.description ?? "NO DATA")
                .onTapGesture {
                    viewModel.removeData()
                }
            Text(viewModel.genericStringModel.info ?? "NO DATA")
                .onTapGesture {
                    viewModel.removeData()
                }
            Text(viewModel.genericBoolModel.info?.description ?? "NO DATA")
                .onTapGesture {
                    viewModel.removeData()
                }
        }
    }
}

구현 화면

profile
JUST DO IT

0개의 댓글