-
화면간 데이터 전달 방법iOS/iOS개념정리 2022. 3. 31. 22:59
화면간 데이터 전달 방법 2가지
1. ViewController 인스턴스화, 다운캐스팅을 통한 프로퍼티 접근
2. delegate 패턴. 이것도 인스턴스화, 다운캐스팅이 필요하지만 화면 전환 후 다시 돌아오는 화면에 데이터 전달 가능1. RootView Controller에서 작성한 label text를 버튼 클릭 > 두번째 화면으로 전달 : 다운캐스팅
- view controller를 전환되려는 화면의 view controller 클래스로 다운캐스팅
- 다른 화면으로 push/present 되기 전에 label text값을 넘겨주면 값이 전달됨
2. 이전 버튼 클릭시 label text 전달 : delegate
두번째 화면인 codePush viewController에서 이전화면인 view controller로 데이터 전달
- protocol 정의
- delegate로 지정 -> 프로토콜을 채택
< 스토리보드에서 segue로 화면 전환 시>
1. prepare메소드 오버라이딩
- 세그웨이를 실행하기 전 시스템에 의해 오버라이드 된 메소드가 자동 호출
이 외에도 방법은 많음. 각자 편한방법을 선택
전환할 화면에 데이터 전달 (Down Casting)
1. 데이터를 전달 받을 라벨 아울렛 변수 추가
2. 데이터를 저장할 변수 추가
@IBOutlet weak var nameLabel: UILabel! // 아울렛 변수 var name: String? // 데이터를 전달받아 저장할 변수
3. View Controller 에서 코드 작성
- ViewController 인스턴스화 메서드에, 전환되는 화면의 ViewController Class 타입으로 다운 캐스팅
ViewController.swift 의 코드
@IBAction func tapCodePushButton(_ sender: UIButton) { // 가고 싶은 뷰를 인스턴스화, 다운 캐스팅 guard let viewController = self.storyboard?. instantiateViewController(withIdentifier: "CodePushViewController) as? CodePushViewController else {return} // name 프로퍼티에 값 전달하기 viewController.name = "Kim Sang Woo 1" // push 로 화면 전환 self.navigationController?. pushViewController(viewController, animated: true)
이렇게 다운캐스팅 하면 그 ViewController 의 프로퍼티에 접근할 수 있게 된다.
4. 전환된 화면에서 데이터를 라벨에 띄워보기
override func viewDidLoad(){ super.viewDidLoad() guard let name = name else {return} self.nameLabel.text = name self.nameLabel.sizeToFit() }
전환된 화면에서 이전 화면에 데이터 전달 (delegate)
ref : https://shark-sea.kr/entry/swift-delegate패턴-알아보기
delegate 패턴
1. Root ViewController 에 데이터를 받을 라벨 추가
2. CodePresentViewController.swift 에 delgate 관련 코드 작성
2-1. 먼저 AnyObject 나 class 를 상속받는 protocol 선언.
위임 받을 때 어떤 기능을 할 것인지 메뉴얼 정의 같은 개념.protocol SendDataDelegate: AnyObject { func sendData(name: String) }
AnyObject 나 class 를 상속하는 프로토콜은, 이 프로토콜은 "오직 클래스에서만 사용이 가능"하다는 것을 의미한다.
2-2. 타입이 protocol 인 delegate property 를 선언
weak var delegate: SendDataDelegate?
weak 을 붙여주지 않는다면 ViewController <-> CodePresentViewController 가 서로를 양방향 참조하기 때문에 ARC 방식인 swift 에서는 메모리가 영원히 해제되지 않게 된다.
메모리 누수 방지를 위해서 weak 을 붙여주는 것이 좋다. 무작정 weak 을 쓸 수 있는 것은 아니고 클래스에서만 사용가능한 프로토콜에서 사용한다.
2-3. delegate 에서 사용할 기능 전달@IBAction func tapBackButton(_ sender: UIButton){ // 기능 전달 self.delegate?.sendData(name: "Kim Sang Woo 3") self.presentingViewController?.dismiss(animated: true, completion: nil) }
3. ViewController 에서 위임자 설정, protocol 채택
guard let viewController = self.storyboard?.instantiateViewController(withIdentifier: "CodePresentViewController") as? CodePresentViewController else {return} viewController.name = "Kim Sang Woo 2" viewController.delegate = self
위 코드는 "CodePresentViewController 의 대리자는 나(self)야." 라는 의미이다.
대리자는 당연히 해야 할 역할이 명시되어있는, 같은 protocol 을 채택해야한다.class ViewController: UIViewController, SendDataDelegate { ... }
class 초반에 SendDataDelegate 프로토콜을 추가한다.
그리고 프로토콜을 준수하기 위해 메서드를 정의해준다.func sendData(name: String){ self.nameLabel.text = name self.nameLabel.sizeToFit() }
그러면 CodePresentViewController.swift 에서 작성했던 코드 self.delegate?.sendData(name: "Kim Sang Woo 3") 가 적용되어 name 에 "Kim Sang Woo 3" 가 저장된다.
Segueway 로 구현된 화면 전달 방식에서 데이터 전달하기 (prepare overriding)
1. SegPushViewController 에 데이터를 받을 라벨 아울렛 변수 추가
2. ViewController 에 prepare 메서드 오버라이딩
- Segueway 로 구현된 화면 전환에서, 데이터를 전달하기 위한 가장 좋은 위치는, 전처리 prepare 메서드prepare 메서드를 오버라이드 하면 Segueway 를 실행하기 직전에 시스템에 의해서 자동으로 호출된다.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let viewController = segue.destination as? SegPushViewController { viewController.name = "Kim Sang Woo 4" } }
3. SegPushViewController 에 라벨 띄우기
override func viewDidLoad(){ super.viewDidLoad() if let name = name { self.nameLabel.text = name self.nameLabel.sizeToFit() } }
delegate 정의 시 weak 를 붙이는 이유는?
var delegete: DeliveryDataProtocol? 로 해도 무방
but
first vc -> second vc를, second vc -> first vc 를 서로 참조하고 있는데 이럴 경우 메모리가 해제되지 않아서
좀비처럼 영원히 남아있게 됨 (ARC의 한계: 순환참조)
이게 하나라면 큰 문제가 없을 수 있겠지만, 좀비가 많이 있다면 앱이 죽을 가능성..
but 무작정 weak를 쓸 수 있는게 아니라,
protocol에서 오직 이 프로토콜은 "클래스에서만 사용이 가능하다" 라는것이 명시가 되어있어야 함
==> protocol에 class 또는 AnyObject를 상속받는다면
이 protocol은 오직 class에서만 사용 가능하다 라는 뜻이 됨
** protocol이 class 또는 AnyObject를 상속받지 않는다면 모든 곳에서 채택이 가능합니다. **
요약하면, weak을 붙이는 이유는 메모리누수를 방지하기 위함
'iOS > iOS개념정리' 카테고리의 다른 글
네트워크 비동기와 reloadData의 중요성 (0) 2023.02.05 Completion Handler / Closure (0) 2022.05.15 Timer class vs. GCD DispatchSourceTimer (0) 2022.05.08 [iOS] Delegate, Notification, KVO 비교 및 장단점 정리 (0) 2022.04.20 KVO (프로퍼티 옵저버) (0) 2022.04.06