[iOS] 화면간 데이터 전달하기

김상우·2021년 11월 23일
2

ref : Fast Campus, https://velog.io/@heyksw/iOS-화면전환-구현-연습


화면간 데이터 전달 방법 2가지

  1. ViewController 인스턴스화, 다운캐스팅을 통한 프로퍼티 접근
  1. delegate 패턴. 이것도 인스턴스화, 다운캐스팅이 필요하지만 화면 전환 후 다시 돌아오는 화면에 데이터 전달 가능
  • 내가 느낀 둘의 차이점
    1번 방법은 그냥 일방적으로 다음 화면에 데이터를 넘겨준다면,
    delegate 패턴은 B 화면에서 class 용 프로토콜 타입 delegate 를 생성해준 뒤 그 A 화면에서 그걸 delegate 위임 받는 것이므로 상호작용 느낌이 크다.

전환할 화면에 데이터 전달 (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 패턴

  • 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" 가 저장된다.


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()
  }
}
profile
안녕하세요, iOS 와 알고리즘에 대한 글을 씁니다.

0개의 댓글