오늘은 그간 프로젝트를 진행해오면서 약간의 의문점을 가졌지만 무심코 지나쳐왔던 VC간의 데이터 전달에 관해 정리해보려고 합니다.
1. Delegate Pattern
1.1 delegate pattern을 사용하는 경우 weak 키워드를 통해 delegate를 선언하는 이유
약한 참조를 의미하는 weak키워드는참조하고 있는 객체가 메모리에서 해제될 때 자동으로 참조하는 객체의 참조값을 nil로 설정하도록 합니다.
weak 키워드를 사용하는 경우
약한 참조로 참조 -> delegate 객체가 소유하는 인스턴스가 메모리에서 해제되었을때, delegate 객체가 인스턴스를 계속해서 참조하지 않도록 합니다
weak 키워드를 사용하지 않는 경우
강한 참조로 참조 -> delegate 객체가 소유하는 인스턴스가 메모리에서 해제되었을때도, delegate 객체가 인스턴스를 계속해서 참조합니다.
따라서 delegate 객체가 인스턴스를 계속해서 참조해야 하는 경우가 아니라면 메모리 누수(memory leak)이 발생할 수 있으므로 가급적 weak 키워드를 사용하여 delegate를 선언해야합니다.
( delegate 객체가 인스턴스를 계속해서 참조해야 하는 예로는 AppDelegate에서 앱의 상태 변화에 따라 뷰 컨트롤러 또는 다른 객체에 이벤트를 전달하는 경우를 예로 들 수 있습니다. 이를 위해 AppDelegate는 UIApplicationDelegate 프로토콜을 구현하고, 해당 프로토콜의 메소드를 사용하여 앱의 상태 변화를 감지하고 처리합니다.)
2. Property
property를 이용해 데이터를 전달하는 경우는 다음화면으로 전환하는 경우(present, push) ViewController에 직접 접근하여 ViewController 내부의 property에 직접 값을 할당해주는 경우입니다. 이때, 화면전환을 실행하지 않으면 절대로 데이터 전달이 일어나지 않습니다.
3. 왜 다음화면 -> 이전화면으로 property를 통해 데이터를 전달 하면 안될까?
보통 이전화면에서 다음화면으로 데이터를 전달하때는 property를 이용해 데이터를 전달하고,
다음화면에서 이전화면으로 데이터를 전달 할 때에는 delegate pattern을 활용해 데이터를 전달하는 것이 일반적입니다.
이때, 두 경우가 바뀐 상황을 가정해보겠습니다.
3.1 이전화면으로 property를 통해 데이터를 전달 하는 경우(B -> A)
—————————————화면전환——————————————
- B ViewController 생성
- A ViewController에 연결된 인스턴스 생성 -> 프로퍼티도 생성
—————————————데이터 전달—————————————
- A ViewController의 인스턴스를 참조
- -> BViewController의 인스턴스가 메모리에서 해제되지 않고 유지(memory leak 발생)
위와 같은 상황이 발생하게 됩니다. 이유는
AViewController 인스턴스가 BViewController 인스턴스를 강한 참조하고 있기 때문입니다.
즉, AViewController가 BViewController를 생성하고 소유하기 때문에, BViewController 인스턴스는 AViewController 인스턴스의 참조계층에서 루트에 해당되고, AViewController가 메모리에서 해제되기 전까지는 BViewController 인스턴스도 메모리에서 해제되지 않습니다.
3.2 다음화면으로 delegate를 통해 데이터를 전달 하는 경우(A -> B)
다음은 Delegate Pattern의 간략한 정의 입니다.
Delegate Pattern은 객체 간 통신 및 이벤트 처리를 위한 디자인패턴 중 하나이며
객체가 다른 객체에게 특정 동작을 위임하고, 그 동작이 수행되거나 이벤트가 발생할 때 해당 객체에 알려주는 방식으로 작동합니다.
3.3 정리
Delegate
각 뷰 컨트롤러가 생성한 델리게이트 객체는 해당 뷰 컨트롤러가 소멸될 때 함께 해제됩니다. 따라서, 델리게이트 패턴에서는 메모리 누수의 위험이 상대적으로 낮습니다.
Property
프로퍼티를 이용한 전달에서는 뷰 컨트롤러 간의 참조 관계가 생기게 됩니다.
즉, AViewController가 BViewController를 present 또는 push할 때 BViewController의 인스턴스를 AViewController의 프로퍼티에 저장하게 됩니다. 이 때, BViewController가 dismiss 또는 pop되더라도 AViewController의 프로퍼티에는 여전히 BViewController의 인스턴스가 남아있을 수 있습니다 -> memory leak 발생
3.4 결론
어플리케이션의 관점에서 A -> B ViewController의 이동과 데이터의 전달은 굉장히 자연스러운 흐름이며 이미 화면 전환이라는 이벤트를 발생시키므로 굳이 Delegate패턴을 사용하는 것은 부자연스러운 선택이라고 볼 수 있습니다.
또한 Delegate를 통한 데이터 전달은 두 ViewController 간의 느슨한 결합을 유지하고, 데이터 전달을 확장하거나 커스터마이징하기에 유연한 방식입니다.
따라서, 데이터 전달이 단방향적이며 일회성이 크다면 위에서 언급한 Property 또는 Closure, Notification Center, Segue를 활용하는 것이 적합합니다.
'ios' 카테고리의 다른 글
[iOS, Swift] SwiftSoup을 이용한 Crolling(웹 크롤링) (0) | 2023.05.24 |
---|