josee2
josee2 Devlog
josee2
전체 방문자
오늘
어제
  • 분류 전체보기 (54)
    • Swift (33)
      • 문법 (33)
    • iOS (13)
    • Algorithm (3)
      • 프로그래머스 (1)
      • BOJ (0)
      • 기타 (2)
    • 일상 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 동시성프로그래밍
  • Sync
  • 프로세스
  • 멀티쓰레드
  • 쓰레드
  • 동시
  • 동기
  • concurrent
  • GCD
  • 문자열 템플릿
  • IOS
  • 서울청년취업사관학교
  • 비동기
  • Async
  • SeSAC
  • 동시큐
  • Swift
  • 직렬
  • 스위프트
  • serial

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
josee2

josee2 Devlog

카테고리 없음

[iOS] - MVVM패턴의 기초 (2) - Observable + Generic

2022. 9. 9. 10:03

Observable + Generic

 

이전 포스팅에서 Observable에 대해 알아보았다.

 

그 땐 Int 타입에 대해서만 다루었었는데 만약 String 값을 넣는다면 어떻게 될까?

 

당연히 타입이 맞지 않기 때문에 Observable은 사용이 불가해질 것이다.

 

그러면 다음과 같이 또 Observable을 만들어 주어야할까???

// In Observable
class Observable {

    var listener: ( (String) -> Void)?

    var value: String {
        didSet {
            listener?(value)
        }
    }

    init(value: String) {
        self.value = value
    }

    func bind(completionHandler: @escaping (String) -> Void) {
        completionHandler(value)
        listener = completionHandler
    }
}

// In ViewController
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var example = Observable(value: "김치찌개")

        example.bind(completionHandler: { (menu) in
            print("오늘점심은 \(menu)!!!")
        })

        example.value = "된장찌개"
        example.value = "돈까스"
    }
}
/*
오늘점심은 김치찌개!!!
오늘점심은 된장찌개!!!
오늘점심은 돈까스!!!
*/

만약 이런식으로 매 번 Observable을 만들어줘야 한다면 너무 비효율적일 것이다.

 

이 때 제네릭(Generic)을 사용한다면 여러 타입(String, Int, Double, Struct...) 등이 들어와도 문제없이 사용이 가능하다.

 

여기서 제네릭이란 간단하게 설명하자면 모든 타입을 아우를 수 있는 타입?이라고 보면된다.

 

보통 T로 사용되며 T의 자리엔 어떠한 타입이 들어와도 된다.

 

제네릭을 한 번 사용해 보자.

// In Observable
class Observable<T> {

    var listener: ( (T) -> Void)?

    var value: T {
        didSet {
            listener?(value)
        }
    }

    init(value: T) {
        self.value = value
    }

    func bind(completionHandler: @escaping (T) -> Void) {
        completionHandler(value)
        listener = completionHandler
    }
}

// In ViewController
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var example = Observable(value: [1, 2, 3, 4, 5])

        example.bind(completionHandler: { (menu) in
            print("오늘점심은 \(menu)!!!")
        })

        example.value = [66, 77, 88, 99]
        example.value = [111, 222]
    }
}

/*
오늘점심은 [1, 2, 3, 4, 5]!!!
오늘점심은 [11, 22, 33]!!!
오늘점심은 [555, 666]!!!
*/

우리가 살펴봐야할 것은 Observable<T> , 타입으로 쓰인 T 그리고 ViewController에서 김치찌개, 된장찌개, 돈가스 대신 Int배열이 들어간 것이다.

 

우선 제네릭을 사용하니 Int배열이 들어가도 문제없이 잘 출력되는 것을 볼 수 있다.

 

그런데 <T> 와 T 가 사용부분이 제네릭에대한 이해가 없으면 조금 헷갈릴 수도? 있을텐데 너무 어렵게 생각할 필요없다.

 

Observable<T>는 Observable 클래스에서 제네릭으로 T를 사용하겠다고 선언하는 것이다.

 

그리고 그냥 T 는 String, Int, Double, Struct 등등 타입이 들어올 수 있도록 하는 자리이다.

 

만약 Observable<A> 라고 했으면 제네릭으로 A를 사용하겠다는 의미이고 위의 T자리 대신 A가 들어가면 되는 것이다.

 

이렇게 우리는 제네릭을 사용하여 반복되게 Observable 클래스를 만들어 줄 필요가 없게되었다.

 


다음 포스팅에선 간단한 프로젝트를 MVVM패턴을 사용해보고 이를 사용해 반응형 프로그래밍에 대해 가볍게 살펴보자.

 

 

저작자표시 비영리 변경금지 (새창열림)
    josee2
    josee2
    iOS 개발자 지망생의 공부기록입니다.

    티스토리툴바