ref : Fast Campus, https://velog.io/@heyksw/iOS-화면전환-구현-연습
- ViewController 인스턴스화, 다운캐스팅을 통한 프로퍼티 접근
- delegate 패턴. 이것도 인스턴스화, 다운캐스팅이 필요하지만 화면 전환 후 다시 돌아오는 화면에 데이터 전달 가능
- 내가 느낀 둘의 차이점
1번 방법은 그냥 일방적으로 다음 화면에 데이터를 넘겨준다면,
delegate 패턴은 B 화면에서 class 용 프로토콜 타입 delegate 를 생성해준 뒤 그 A 화면에서 그걸 delegate 위임 받는 것이므로 상호작용 느낌이 크다.
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() }
ref : https://shark-sea.kr/entry/swift-delegate패턴-알아보기
delegate 패턴
- delegate 패턴은 iOS 에서 자주 사용되는 디자인 패턴.
- 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" 가 저장된다.
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() } }