[TIL]08.04

rbw·2022년 8월 4일
0

TIL

목록 보기
38/97
post-thumbnail

loadView 와 viewDidLoad 차이

먼저, loadView 메서드는 뷰 컨트롤러가 자신의 뷰를 접근 하는 self.view 처럼 해당 뷰컨의 메인 뷰를 로드할 때 호출되는 메서드 입니다. 따라서, 메인 뷰를 생성하려고 호추랗는 메서드 임다. 그래서 이 메서드 안에서 새로운 뷰를 만들어서 반환 해주는 경우도 많슴다. 스토리보드를 사용하는 경우에는 굳이 필요하지는 x

viewDidLoad 이 친구는 많이보져? 얘는 뷰가 모두 생성되고 메모리에 생성된 후에 호출되는 메서드입니다. 뷰 컨트롤러의 메인 뷰가 생성 되었으니 이제 이 위에 설정 해줘야 하는 것들이 있다면 여기에 하면 됩니다.

추가로 뷰 컨트롤러의 기본 뷰를 커스텀 하는 경우에 loadView를 자주 활용 한다고 함니다. loadView 에서 새로운 뷰를 생성 후 return 하여 커스텀하게 설정이 가능 함다. 반면에 기본 UIView를 뷰컨의 기본 뷰로 사용하고 그 위에 무언가 얹거나, 뷰가 생성된 이후에 어떤 설정을 하서 사용한다면 viewDidLoad를 사용 하시면 됩니다 !

그리고 뷰 로딩을 직접 처리 하기 위해 loadView을 사용하는 경우에는 super.loadView()를 호출하지 마라고 애플 문서에 나와있숨다 ! Apple doc: “Your custom implementation of this method should not call super.”

ViewController의 View 생성 과정

  1. viewController.view등의 UIViewController객체의 view property에 접근

  2. 메모리상에 view가 존재하지 않으면, loadView가 호출

  3. loadView가 override가 되어 있으면, 그 안의 내용을 생성

  4. loadView가 override가 안되어 있다면, nibName, nibBundle properties의 nib파일의 로드를 시도

  5. 4에서 파일이 존재하지 않으면, ViewController 이름의 nib파일의 로드를 시도

  6. 그래도 없다면, empty UIView를 생성

  7. viewDidLoad를 호출하여줌.

의존성

어떠한 클래스가 다른 클래스나 모델 없이는 내부 로직을 실행할 수 없다면 해당 클래스는 다른 클래스나 모델에 의존성을 가지고 있다라고 표현한다.

이렇게 의존성을 가지게 된다면, 테스트가 어렵고 강한 결합을 가지게 된다. 이러한 결합은 모듈화를 할 때 많은 불편함을 야기시킨다.

그래서 의존 관계 역전 원칙이라는 객체지향 설계 개념 중 하나를 사용하여 이러한 의존 관계를 역전하곤 한다.

해당 원칙에 따르면, 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존관계를 반전(역전) 시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립 되게 할 수 있다. 원칙의 내용은 다음과 같다.

  1. 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
  2. 추상화는 세부 사항에 의존해서는 안된다. 세부 사항이 추상화에 의존 해야한다.

제어의 역전 (Inversion of Control)

코드를 보며 살펴 보겠슴니다

protocol SomeNetworkServiceType {
    func fetchData()
}

class SomeNetworkService: SomeNetworkServiceType {
    func fetchData() {
        print(#function, "이 먼저 실행되어야함")
    }
    
    func configureSomeNetworkDetails() {
        // do something
    }
}

네트워크 서비스에 프로토콜을 정의하여서 네트워크 서비스가 맡아야할 책임을 정의 해주었습니다.

다음 viewModel의 코드로는,

class SomeViewModel {
    let dependency: SomeNetworkServiceType = SomeNetworkService()
    
    // dependency.fetchData함수를 실행해야만 하는 함수
    func viewModelFunction() {
        dependency.fetchData()
        print("dependency에서 가져온 data를 business logic으로 처리")
    }
}

dependency가 프로토콜의 타입을 따르고 있으므로, 위의 네트워크 서비스의 함수인 configureSomeNetworkDetails에 접근을 할 수 없게 되었습니다.

이 부분을 잘 몰랐는데, 이번에 알게 되었다. good

이는 제어의 주체가 네트워크 서비스(class - 세부사항)에서 SomeNetworkServiceType(protocol - 추상화)로 바뀌게 되었습니다.

아직 이것만으로는 테스트가 쉬워지거나 강한 결합이 느슨해지지는 않고, 또 다른 방법을 사용해야 합니다. 주로 말하는 의존성 주입 을 도입해야함니다

의존성 주입에서 주로 사용하는 방법은 생성자 주입 입니다.

class SomeViewModel {
    let dependency: SomeNetworkServiceType
    
    init(dependency: SomeNetworkServiceType) {
        self.dependency = dependency
    }
    
    // dependency.fetchData함수를 실행해야만 하는 함수
    func viewModelFunction() {
        dependency.fetchData()
        print("dependency에서 가져온 data를 business logic으로 처리")
    }
}

let dependency = SomeNetworkService()
let viewModel = SomeViewModel(dependency: dependency)

위의 코드처럼 init을 사용하여 의존성을 주입하는 방법을 주로 사용하곤 합니다.


참조

https://mrgamza.tistory.com/279

https://yagom.net/forums/topic/loadview%EC%99%80-viewdidload-%EC%B0%A8%EC%9D%B4%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A7%88%EB%AC%B8%EC%9E%85%EB%8B%88%EB%8B%A4/

https://velog.io/@hansangjin96/Swinject-%EC%9D%98%EC%A1%B4%EC%84%B1-%EA%B4%80%EB%A6%AC%EB%9E%80

profile
hi there 👋

0개의 댓글